Here you will see tutorial on Spring Boot + ReactJS Example. We have seen many examples of Spring MVC web application application using JSP as a front-end technology but here we will use ReactJS as a front-end technology to represent our UI. We have also seen how to Create CRUD Web App using Spring + AngularJS. You can also find my other tutorials on ReactJS.

Here we will use Java version 8, Spring Boot version 1.5.9.RELEASE and node version 6.11.3 and npm version 3.10.10.

We basically create two projects – one is frontend or client side called web-app and another one is backend called java-app.

Obviously as the name suggests web-app, so it will contain only client side technologies to build the application whereas java-app will contain only Java technologies to build the application.

Prerequisites

knowledge of Spring, Java
Knowledge of ReactJS

Softwares

Eclipse Neon
JDK 8, Spring Boot 1.5.9.RELEASE
Have gradle installed and configured
Have JDK installed and configured
Have npm installed and configured

Let’s move on to the Spring Boot + ReactJS CRUD example…

Implementing server side code – Spring Boot

Setting up project

Create a gradle based project in Eclipse. Once you successfully create the structure try to build the project by executing the gradle command gradle clean build on the root directory using cmd window. Your build.gradle file under java-app project should contain below:

buildscript {
    ext {
        springBootVersion = '1.5.9.RELEASE'
    }
    repositories {
        mavenLocal()
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'

sourceCompatibility = 1.8 
targetCompatibility = 1.8

jar {
    baseName = 'SpringBootReactJS'
    version = '0.0.1-SNAPSHOT'
    manifest {
        attributes("Main-Class": "com.jeejava.app.Application")
    }
}

repositories {
    mavenLocal()
    mavenCentral()
}
    
dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")
}

If you face any issue related to main class exception during build then you need to create the Application.java under package com.jeejava.app with main method in it and re-build the java-app.

Creating a model class

Create below model class that will give us object as per our needs. This class has few attributes to hold about the website information.

public class Website {
    private Integer id;
    private String url;
    private String title;
    
    //getters and setters
}

Creating repository class

You need to create below repository class in order to provide the data to the consumers who will consume from your REST services. Ideally your source of data should be some persistence storage like database but for our example purpose this will be sufficient.

It is straight forward and self-explained for CRUD operations.

@Component
public class WebsiteRepository {
    private static final Map<Integer, Website> WEBSITES = new HashMap<>();
    private static Integer counter = 1;
    public List<Website> findAll() {
        return new ArrayList<>(WEBSITES.values());
    }
    public Website findById(Integer id) {
        return WEBSITES.get(id);
    }
    public void add(Website website) {
        counter++;
        website.setId(counter);
        WEBSITES.put(counter, website);
    }
    public void update(Website website) {
        WEBSITES.put(website.getId(), website);
    }
    public void delete(Integer id) {
        WEBSITES.remove(id);
    }
}

Creating Spring service class

Any business logic or processing should be written in the service layer code and should be loosely coupled. Here I will only create class but ideally you should create Interface and class should implement the Interface.

@Service
public class WebsiteService {
    @Autowired
    private WebsiteRepository websiteRepository;
    public List<Website> getWebsites() {
        System.out.println("Total Websites: " + websiteRepository.findAll().size());
        return websiteRepository.findAll();
    }
    public Website getWebsite(final Integer id) {
        if (id == null || id == 0) {
            throw new RuntimeException("You must provide valid website id");
        }
        Website website = websiteRepository.findById(id);
        if (website == null) {
            throw new RuntimeException("Website detail not found for the given id => " + id);
        } else {
            return website;
        }
    }
    public void deleteWebsite(final Integer id) {
        if (id == null || id == 0) {
            throw new RuntimeException("You must provide valid website id");
        }
        try {
            websiteRepository.delete(id);
        } catch (Exception e) {
            throw new RuntimeException("Website detail not found for the given id => " + id);
        }
    }
    public void saveWebsite(final Website website) {
        if (website == null || (website.getTitle() == null && website.getUrl() == null)) {
            throw new RuntimeException("You must provide Website details");
        }
        try {
            websiteRepository.add(website);
        } catch (Exception e) {
            throw new RuntimeException("Error occurred during website details saving");
        }
    }
    public void updateWebsite(final Website website) {
        if (website == null || ((website.getId() == null || website.getId() == 0) && website.getTitle() == null && website.getUrl() == null)) {
            throw new RuntimeException("You must provide Website details");
        }
        try {
            websiteRepository.update(website);
        } catch (Exception e) {
            throw new RuntimeException("Error occurred during website details updating");
        }
    }
}

Creating Spring REST controller class

You will provide REST service end-points in order to let consumers consume the data from your services. So here it is.

@RestController
public class WebsiteRestController {
    @Autowired
    private WebsiteService websiteService;
    @GetMapping("/websites")
    public ResponseEntity<List<Website>> getWebsites() throws Exception {
        return new ResponseEntity<List<Website>>(websiteService.getWebsites(), HttpStatus.OK);
    }
    @GetMapping("/website/search/{id}")
    public ResponseEntity<Website> getWebsite(@PathVariable Integer id) throws Exception {
        return new ResponseEntity<Website>(websiteService.getWebsite(id), HttpStatus.OK);
    }
    @PostMapping("/website/add")
    public ResponseEntity<Void> saveWebsite(@RequestBody Website website) throws Exception {
        websiteService.saveWebsite(website);
        return new ResponseEntity<Void>(HttpStatus.OK);
    }
    @PostMapping("/website/update")
    public ResponseEntity<Void> updateWebsite(@RequestBody Website website) throws Exception {
        websiteService.updateWebsite(website);
        return new ResponseEntity<Void>(HttpStatus.OK);
    }
    @GetMapping("/website/delete/{id}")
    public ResponseEntity<Website> deleteWebsite(@PathVariable Integer id) throws Exception {
        websiteService.deleteWebsite(id);
        return new ResponseEntity<Website>(HttpStatus.OK);
    }
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedOrigins("*");
            }
        };
    }
}

Notice how I have avoided error No ‘Access-Control-Allow-Origin’ header is present on the requested resource using WebMvcConfigurer.

Creating Spring Boot main class

Now when you are ready to deploy with your coding done then you need to have some trigger point through which you will deploy your application. Here is the standalone main class that deploys your Spring Boot application into Tomcat container.

@SpringBootApplication(scanBasePackages = "com.jeejava")
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

If you want to change the default port of Tomcat then you can do this by updating into application.properties file, for example, to run the server on port 9999:

server.port=9999

Implementing client side code – ReactJS

Now we will see how do we create client side UI code using ReactJS framework.

Setting up the project

Create a directory called web-app and ow navigate to the directory web-app in cmd window and run the below command to create required modules and project structures under web-app directory.

Please read how to setup node.js in Windows before you create the ReactJS application.

>create-react-app web-app

We will write everything into js (javaScript) files under src folder. We want to keep each component’s js file under src/components. Therefore create components directory under src folder.

So the typical directory structure of web-app would be similar to below image:

reactjs

Apply some style

Create below website.css file under src directory to apply some basic style to the UI.

#container {
	width: 800px;
	margin: auto;
}
table {
	border-collapse: collapse;
	width: 800px;
	margin: 10px auto;
}
th, td {
	border: 1px solid #ddd;
	text-align: left;
	padding: 8px;
}
tr:nth-child(even) {
	background-color: #f2f2f2
}
tr:hover {
	background-color: #ddd;
}
th {
	padding-top: 12px;
	padding-bottom: 12px;
	text-align: left;
	background-color: #4CAF50;
	color: white;
}

Creating js files for CRUD operations

Create a folder called components under src folder where we will put our js files.

index.js file

This file is the root file and it defines all paths required to navigate once your application functionality is displayed on ReactJS UI. You may click on link for creating new website, you may click on update link for updating existing website information etc.

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import './website.css';
import Websites from './components/websites';
import Create from './components/create';
import Update from './components/update';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(
	<Router>
		<div>
			<Route exact path='/' component={Websites} />
			<Route path='/create' component={Create} />
			<Route path='/update/:id' component={Update} />
		</div>
	</Router>,
document.getElementById('root'));

registerServiceWorker();

The registerServiceWorker.js file has already been created under the src folder during the initial ReactJS project creation.

Retrieve all websites

Create below websites.js file under src/components directory, which will hold all the logic to retrieve all websites and display on a HTML table. In each row we will provide two links – edit, for updating the existing website and delete, for deleting the existing website.

We will also provide Create Website link on top of the table, using which you will be able to add new website information to the server side.

You may find more on componentDidMount. We have exported the class as export default <component name> to use (import) it elsewhere as you have seen in the index.js file.

import React from 'react';
import { Link } from 'react-router-dom';

class Websites extends React.Component {
	constructor(props) {
		super(props);
		this.state = {websites: []};
		this.headers = [
			{ key: 'id', label: 'Id'},
			{ key: 'title', label: 'Title' },
			{ key: 'url', label: 'URL' }
		];
		this.deleteWebsite = this.deleteWebsite.bind(this);
	}
	
	componentDidMount() {
		fetch('http://10.2.226.115:9999/websites')
			.then(response => {
				return response.json();
			}).then(result => {
				console.log(result);
				this.setState({
					websites:result
				});
			});
	}
	
	deleteWebsite(id) {
		if(window.confirm("Are you sure want to delete?")) {
			fetch('http://10.2.226.115:9999/website/delete/' + id)
				.then(response => { 
					if(response.status === 200) {
						alert("Website deleted successfully");
                                                fetch('http://10.2.226.115:9999/websites')
						.then(response => {
							return response.json();
						}).then(result => {
							console.log(result);
							this.setState({
								websites:result
							});
						});
					} 
			 });
		}
	}
	
	render() {
		return (
			<div id="container">
				<Link to="/create">Add Website</Link>
				<p/>
				<table>
					<thead>
						<tr>
						{
							this.headers.map(function(h) {
								return (
									<th key = {h.key}>{h.label}</th>
								)
							})
						}
						  <th>Actions</th>
						</tr>
					</thead>
					<tbody>
						{
							this.state.websites.map(function(item, key) {
							return (
								<tr key = {key}>
								  <td>{item.id}</td>
								  <td>{item.title}</td>
								  <td>{item.url}</td>
								  <td>
										<Link to={`/update/${item.id}`}>Edit</Link>
										 
										<a href="javascript:void(0);" onClick={this.deleteWebsite.bind(this, item.id)}>Delete</a>
								  </td>
								</tr>
											)
							}.bind(this))
						}
					</tbody>
				</table>
			</div>
		)
	}
}

export default Websites;

Creating website

You need to create below js file under src/components directory, which will hold all the logic to add new website information. It will display a form where user inputs website information and click on Submit button to add the website information.

Once you add successfully, an alert box will show you successful message.

You will also be given a link that will take you to the list of websites page.

import React from 'react';
import { Link } from 'react-router-dom';

class Create extends React.Component {
  constructor(props) {
    super(props);
    this.state = {title: '', url:''};
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }
  handleChange(event) {
	  const state = this.state
	  state[event.target.name] = event.target.value
	  this.setState(state);
  }
  handleSubmit(event) {
	  event.preventDefault();
	  fetch('http://10.2.226.115:9999/website/add', {
			method: 'POST',
			body: JSON.stringify({
							title: this.state.title,
							url: this.state.url
			}),
			headers: {
							"Content-type": "application/json; charset=UTF-8"
			}
		}).then(response => {
				if(response.status === 200) {
					alert("New website saved successfully");
				}
			});
  }
  render() {
    return (
		<div id="container">
		  <Link to="/">Websites</Link>
			  <p/>
			  <form onSubmit={this.handleSubmit}>
				<p>
					<label>Title:</label>
					<input type="text" name="title" value={this.state.title} onChange={this.handleChange} placeholder="Title" />
				</p>
				<p>
					<label>URL:</label>
					<input type="text" name="url" value={this.state.url} onChange={this.handleChange} placeholder="URL" />
				</p>
				<p>
					<input type="submit" value="Submit" />
				</p>
			  </form>
		   </div>
    );
  }
}

export default Create;

Updating website

Create below js file under src/components directory, which will hold all the logic to update existing website information. It will display a form where user modifies the existing website information and click on Submit button to update the website information.

We pass website id value with the browser URL as a path parameter and that’s why we have the route path as /update/:id in the index.js file. Accordingly we have added Link element in the table for editing exiting information. Using this id value we first fetch the website information from server and populate the form fields in update page.

Once you update successfully, an alert box will show you successful message.

You will also be given a link that will take you to the list of websites page.

import React from 'react';
import { Link, withRouter } from 'react-router-dom';

class Update extends React.Component {
  constructor(props) {
    super(props);
    this.state = {id: '', title: '', url: ''};
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }
  
  componentDidMount() {
	fetch('http://10.2.226.115:9999/website/search/' + this.props.match.params.id)
		.then(response => {
			return response.json();
		}).then(result => {
			console.log(result);
			this.setState({
				id:result.id,
				title:result.title,
				url:result.url
			});
		});
  }
  handleChange(event) {
	  const state = this.state
	  state[event.target.name] = event.target.value
	  this.setState(state);
  }
  handleSubmit(event) {
	  event.preventDefault();
	  fetch('http://10.2.226.115:9999/website/update', {
			method: 'POST',
			body: JSON.stringify({
							id:this.state.id,
							title: this.state.title,
							url: this.state.url
			}),
			headers: {
							"Content-type": "application/json; charset=UTF-8"
			}
		}).then(response => {
				if(response.status === 200) {
					alert("Website update successfully.");
				}
			});
  }
  
  render() {
    return (
			<div id="container">
			  <Link to="/">Websites</Link>
				  <p/>
				  <form onSubmit={this.handleSubmit}>
					<input type="hidden" name="id" value={this.state.id}/>
						<p>
						<label>Title:</label>
							<input type="text" name="title" value={this.state.title} onChange={this.handleChange} placeholder="Title" />
						</p>
						<p>
							<label>URL:</label>
							<input type="text" name="url" value={this.state.url} onChange={this.handleChange} placeholder="URL" />
						</p>
						<p>
							<input type="submit" value="Submit" />
						</p>
				  </form>
			   </div>
    );
  }
}

export default Update;

Deleting website

You click on the Delete link given on table at each row on the right side to delete the existing website information. When you click on the Delete link you will be shown an alert box to get confirmation whether you really want to delete. If you click on yes then only website information will get deleted from server otherwise you will stay on the same page.

The delete functionality is given in the websites.js file.

Notice how I have used normal anchor link <a/> to create delete link for deleting website information.

Note: if you receive module react-router-dom is not found then you can install it using command npm install –save react-router-dom.

Testing the application

Now you have to first deploy the Spring Boot application. So just run the main class and relax. Here you will find the feeling of Spring Boot + ReactJS example.

Next to run your ReactJS application, navigate to the directory web-app in cmd window and execute the command npm start. A browser with URL http://localhost:3000/ will automatically open and a home page gets displayed with no website listed in the table but you will see only table headers.

spring boot reactjs crud

Now try to add a new website by clicking on the link Add Website, you have to fill title and URL of the website and click on Submit button. A new website gets created and you will see an alert box showing “New website saved successfully” similar to below image:

spring boot reactjs crud

Now when you click on Websites link will find a new website information in the home page.

spring boot reactjs crud

 

Next you may want to update the existing website. So let’s update by clicking on the edit link given on the right side of the table row. A form with auto-populated existing website information will be opened and once you update by clicking on the Submit button, you will see an alert box showing “Website updated successfully”:

spring boot reactjs crud

Now you will get updated list on home page:

spring boot reactjs crud

Now if you want to delete the website then you may click on Delete link. When you click on Delete link you will get an alert box for confirmation whether you really want to delete or not?

spring boot reactjs crud

When you click yes then above row will get deleted and you will be left with no more website.

spring boot reactjs crud

Improvements

There are many areas you can improve in the example Spring Boot + ReactJS CRUD Example. Some of the them are given below:

1. Look and feel of the UI
2. Validation of the input fields
3. When you add or update website information then you can navigate to the list of websites page
4. Error handling, currently I am only checking http status 200
5. Apply security with roles
…more

That’s all. Hope you got idea how to create Spring Boot + ReactJS CRUD example.

Thanks for reading.

Tags:

I am a professional Web developer, Enterprise Application developer, Software Engineer and Blogger. Connect me on Roy Tutorials | TwitterFacebook Google PlusLinkedin | Reddit

Leave a Reply

Your email address will not be published. Required fields are marked *