Spring Boot React.js Full Stack Tutorial By Example

Today we will look at building a web app using Sprint Boot and React.js. We will look at a number of different tutorials out there to see if we can get a simple view of how we can do this, as there are a dazzling array of technologies and libraries and frameworks out there at the mo. Without good examples and tutorials to work with it can be difficult to make up your mind which ones to choose.

The way im going to do this of course is by looking at the existing tutorials that are out there, and use those as a guide to them come up with my own tutorial. Im going to do all this in one article so that we dont have to jump around. Lets have a look at the key technologies we have mentioned first so that we know what we are talking about.

Why Spring Boot and React.js?

Combining Spring Boot and React.js should allow us to combine the robustness of Java and Spring on the backend, with the component driven client model on the front end, and allows to carve out well designed UI apps. But throughout this tutorial we will see how easy this is to do (or not!).

What is Spring Boot?

Spring Boot is part of the Spring Framework. The Spring Framework is a set of java libraries designed to support the development of Java applications by implementing and simplifying many well known design patterns, with the underlying goal of making Java development and support easier.

Spring boot extends that idea by making a certain number of assumptions about your application, and using those to enable automatic configuration to get your application up and running without endless configuration. It also includes and embedded web server so you can get applications that need an application server running out of the box almost immediately.

What Is React.js?

React.js also known simply as React, is a client user interface JavaScript library. It is used for building user interfaces and takes a component driven approach to building those UIs. The main benefits that are given for React is that it performs well and is relatively easy to learn.

React.js and Spring Data REST – Spring.io

Over at Spring.io there is a tutorial that looks at building combining Spring Boot and React.js to build a web app. Find that tutorial here.

If you dont know what Spring Data REST is, its part of Spring that exposes hypermedia driven HTTP resources. For the purposes of what we are doing, we dont really care about it too much, the tutorial uses Spring Boot and React.js, which are the bits we are focusing on for now.

Setting Up The Eclipse Maven Project

To get started, the tutorial tells us to setup start.spring.io/ with Rest Repositories, Thymeleaf, JPA and H2 as dependencies so lets do that bit first.

Lets fill in the following values at start.spring.io

Click to ‘Generate A Project’ and the project config should get downloaded.

Im using Eclipse, and like to use the eclipse maven plugin, so I unpacked the zip file and copied the resources from there into a new Eclipse java project of the same name, springbootreact1.

We get a default Spring Boot application in com.colwil.springbootreact1

I then run the eclipse maven plugin, ‘eclipse:clean eclipse:eclipse -DdownloadSources -DdownloadJavadocs’ and end up with the following:

Setting up the Demo Objects

We need the domain object, repository, and some sample data as per the tutorial. So lets get those bits out of the way first.

First we create an Employee object

Then we create the EmployeeRepository. This extends Spring Data RESTs CrudRepository to give us CRUD methods to use out of the box.

Then we create a DatabaseLoader class to give us some sample data. The annotations mean that this automatically gets run and the constructor is annotated so that it has access to the EmployeeRepository that we created.

Spring Data will generate the required database statements based on the methods in the repository class that was created.

REST Application Config

The only thing we need to configure at this stage is Spring Data REST. We need to adjust its default URI so it doesnt conflict with the UI we are going to build. So we add the following property to the application.properties file already in the src/main/resources folder.

For some reason the maven eclipse plugin excludes application.properties from the build path so had to modify the build path for that change to go through.

On further investigation it turns out to be related to a default in the pom.xml. So we need to switch off filtering for the src/main/resources directory as below… otherwise exclusions are added to the build path.

Launching The REST API

To run the application we run the main method of our application that was built for us by the Spring Initializer.

Right click in eclipse and Run as.. java application gives the following

Testing The REST Service

Testing the REST service at this stage is as simple as accessing the URL at localhost:8080/api in the browser.

Yehhhh we have got a JSON message back. Hmmm, but theres a problem here. We are only getting the profile links, and not getting the employees link as in the tutorial, so something somewhere has gone wrong.

The problem is that the DatabaseLoader class that implements Springs CommandLineRunner interface is not being executed. After puzzling this out, I realised its because our CommandLineRunner, Entity and Repository are not in the same package as our Spring Application class. When I setup the application via the Spring Initializer i specified ‘com.colwil’ as the package, but the code from the tutorial is using com.greglturnquist.payroll.

So what this highlights is that Spring Boot has made assumptions and applied some defaults. Naturally if you go away from those defaults Spring Boot is not going to work properly, so you need to let it know about any diversions from the defaults.

So in this case by default Spring Boot is scanning the packages that are in the hierarchy of the class annotated with @SpringBootApplication. As our classes are elsewhere, we need to tell Spring Boot where to look with the @ComponentScan(“com.greglturnquist.payroll”) for the CommandLineRunner, @EnableJpaRepositories for the repository and the @EntityScan for the entity. So we change our Springbootreact1Application as below, specifying the packages where the CommandLineRunner, Entity and Repository .

If we rerun our Spring Boot app and access the url again.

This time we get links for both employees and profile. Much better! If we access the link that we have been given for the employees at http://localhost:8080/api/employees, we can actually see the Employee data that has been setup by the DatabaseLoader.

Setting Up The Spring MVC Controller For The React UI

At this point we need to create a home for the React components to live in. We do this by creating a Spring MVC controller and defining a Thymeleaf HTML template.

The Spring MVC Controller

As mentioned in the tutorial, the @Controller identifies this as a Spring MVC controller, the request mapping maps slash to the index method and index is the prefix of the html page to use.

The index.html Thymeleaf template

The index.html template needs to live in src/main/resources/templates folder.

The div with id=”react” and the bundle.js have significance and those will get investigate those once we have built and setup the front end dependencies.

Installing Node.js and React.js Using The Pom.xml

As per the tutorial, we need to use the frontend-maven-plugin to enable us to

  • Install node.js and npm package manager
  • Install the node.js modules configured in package.json
  • run webpack to compile all the JavaScript components into a single file

So lets add the plugin config for frontend-maven-plugin to our pom, and run the build.

So the build failed because of 1 error and 1 warning

So npm install failed as we havent created our package.json file yet

and webpack failed as we havent created our config for webpack, so lets create those

package.json

webpack.config.js

Now lets rerun the maven build.

ok so this time our npm install was successful

but the webpack build failed

its because we havent created the /src/main/js/app.js that defines the modules. So lets add that as per the tutorial.

and run the build again.

So the webpack build failed again with a different error.

we also need to add the src/main/js/client.js which is one of the modules needed for HAL and URI Templates.

and rerun the build, which fails again

looks like theres some more modules missing. Looking at the tutorial these arent mentioned, but look at the github for the tutorial, /api/uriTemplateInterceptor.js and /api/uriListConverter.js are there. So lets grab those too and rebuild the project.

Success!

Building the React.js UI

So now we are ready to play with React more. As per the tutorial we want to add in a top level component.

In the App component, an array of employees is fetched from the Spring Data REST backend and stored in this component’s state data.

https://spring.io/guides/tutorials/react-and-spring-data-rest/

also in app.js

class Foo extends React.Component{…​} is the method to create a React component.
componentDidMount is the API invoked after React renders a component in the DOM.
render is the API to “draw” the component on the screen.

https://spring.io/guides/tutorials/react-and-spring-data-rest/

So what we see here is that theres a class with a constructor to setup the React component…

then theres a componentDidMount() method. Once the component is added to the DOM, the componentDidMount() method will be called.

In this case its using the Node module, rest.js, (with additional functionality added round it for processing REST Data), and calling the GET method in our Spring MVC REST to get the employees, then calling this.setState to set employees to the employees in the response message.

Heres the description of the Node rest.js module

rest.js

Just enough client, as you need it. Make HTTP requests from a browser or Node.js applying only the client features you need. Configure a client once, and share it safely throughout your application. Easily extend with interceptors that wrap the request and/or response, or MIME type converters for rich data formats.

https://www.npmjs.com/package/rest

Calling this.setState schedules a UI update, which will trigger React to check if the state has changed and call the render() method again.

So you initialise your attributes in the constructor, and check for changes in componentDidMount. Keep in mind that in React, state represents data that can change, but properties represent fixed values that wont change.

Adding the rest of the details to the app.js, first we just have the variables/requires

then we have the app component that grabs the Spring MVC data REST response and sticks that in an EmployeeList component

Then we have the EmployeeList component, that with HTML formatting and also creating each Employee

then we have the Employee component

The above sections are part of app.js. As it appears we are mixing HTML and Javascript into something called JSX. The advantage here with react is using smaller understandable components to create larger components.

The last steps is to take out components and to add them to the HTML page

App is our top level component in App.js, and ‘react’ is the <DIV> element we created in our HTML page. So this applys the react components to that div element in the HTML page.

Running The Application

First step now that we have all the source code in place, is to rebuild the project in eclipse

One other thing to make sure is that Springs application.properties is in the root of the target folder. in my eclipse for some reason the project was set to ignore that, so it wasnt getting created, which would cause the Spring MVC URL not get set properly.

Now lets run Spring Boot and confirm we can see the data.

Success! We have the data as per the tutorial. Now lets continue with the rest of the tutorial.
So now we have 1 employee, lets add another one as per the tutorial, using curl.

Heres our curl command run at the command line.

and heres the response also at the command line.

So if we refresh the app, we should see the additional employee.

Success!

What Did We Achieve So Far?

  • Created 2 React Components
  • Used Spring Data REST to populate those with data from a domain object and repository

In the next part of the tutorial, they hope to get us to make this app dynamic load data, use the hypermedia controls in the app, and also allow you to edit the data.

Navigating The Application Using The HyperMedia Controls

The next stage of the tutorial is around actually using the links included in the Spring REST data to provide navigation around the app.

Updating The Code To Include Paging

Currently the EmployeeRepository extends CrudRepository that provides CRUD operations (even though we havent implemented them all in the React app).

The description of that in the code is

But for paging we need the EmployeeRepository to extend PagingAndSortingRepository.

The description of that in the code shows that it extends CrudRepository plus adds additional pagination and sorting methods.

Also at this point we add some more initialisation to the DatabaseLoader so we have some more test data.

If we rerun the app and refresh we can see the additional data.

We dont see the the additional links yet, as we havent updated the front end React part of the app.

Testing The Paging In The Rest API With Curl

If we run the curl command from the command line, we should see the result of the REST API now that we have added the paging. Lets run the curl command in the same way that they do in the tutorial. The results actually come out in a different order.

Heres what we get if we navigate to the next link http://localhost:8080/api/employees?page=1&size=2

We get the next page of results and updated links for paging. At this point the section is done, so we need to update the React frontend to process the additional features we have added.

Navigating the Spring Data Rest

In the tutorial they add a new javascript file to handle the following of the URLs,

In app.js, the componentDidMount() method changes. Rather than calling the REST api from componentDidMount(), then using this.setState(), the tutorial users a new loadFromServer() method.

Heres is the new app.js so you can see the whole. Then lets look at each of the areas that the tutorial talks about so we are clear that we understanding it.

Lets look at the loadserver() method first as thats what the tutorial talks about next.

The loadServer() method first calls the follow() method first, passing the client object to make the rest calls, the starting or root URI, and then the name of the relationship to look for in the returned JSON message.

So here its marked as employees, so from the JSON message we had earlier from CURL it looks like below.

Then the loadFromServer() method will first get the JSON schema information

, and then get the employee data itself

The metadata is then used in the UI.

Create New Records With The CreateDialog React Component

In the updated app.js the render() method for App is as follows

So you can see that it has a new component, CreateDialog, followed by the EmployeeList component. This new component is where the create part of CRUD functionality is handled in the UI. The CreateDialog class looks like this

As per the tutorial lets look at what the render part of this new component does first.

if you remember earlier we loaded the schema into

So the name of each field is listed in the schema and is now in the attributes property. The first steps of the render method is to create an input field for each field in the schema, which is what the below does and stores it in inputs.

then it returns the UI details that includes a form where the Create button is processed by the handleSubmit() method.

So when you fill in the values on the input form and click the Create button, the handleSubmit() method will be called to process the form.

The handleSubmit() method will

disable any default browser behavior normally perform on submitting a form by calling the preventDefault() react method

create a new variable, newEmployee to hold the employee details

loop through the input fields in the submitted form to extract the values that have been entered and save them in the newEmployee variable

call the onCreate() method to process to new employee

loop through the input fields and set them to blank to reset them

Navigates to the anchor to close the window

If we look at the component the # has a class with associated css on it to close the window.

This is also a link in the component, so if you click close or after processing submit you invoke the close class as below.

The additional css to process the component in main.css.

The App.onCreate() method is called to process the new employee

lets break down what this does

First navigates to the employees URL

then does a POST to process the new employee

then it reloads the employees

then navigates to the last pages if its available using the onNavigate() method.

What Is A Promise In Javascript?

As mentioned in the tutorial, Javascript libraries like react rely heavily on promises. The concept of a promise is that its a way of waiting for the result of a long running task. Given that everything in Javascript executes on a single thread… if you block that basically everything in your UI app stops working.

Promises are a way of dealing with the single UI thread issue. With a promise, you get notified when the the response/value is available, or if theres an error when the error is available. Heres an example to show the usefulness of a promise.

The above code is synchronous, if the helloWorld() method access some other service that hangs, the UI is now blocked until that responds or fails.

If we use a promise by using the .then() function, we will get notified when the value is fulfilled, but the rest of the code is not blocked as this is asynchronous, so other code in the UI will continue while this waits for a response

Page Navigation In The React App

In the EmployeeList component, the render() method includes links for navigation, based on whether they are available in the list. The navLinks array will contain a list of the HTML buttons, and theres a <div> containing those included in the output of the EmployeeList component.

There are methods defined to handle the button clicks also…

These handlers call preventDefault() to stop any default behaviour for the buttons, and then call the onNavigate() method, as shown below, to navigate to the requested page.

Deleting Employees From The React UI

Lets look at how the latest version of the code in the app shows how a delete of an employee is processed. If we look at the latest version of the Employee class we can see that in the render method theres a Delete button defined

This button has an onClick event that will call this.handleDelete.

You can see in the constructor that this is bound to the this.handleDelete variable. This is because in Javascript this doesnt happen by default. So if you didnt bind, when the onClick runs, this would not be available so you would probably get an error or the onClick wouldnt work. If you looks at the React documentation it explains it and also shows other ways to achieve the same thing, but this appears to be the cleanest way.

When the button is clicked, the handleDelete() method is called then.

The handleDelete() method calls onDelete() and passes it the employee. If you are wondering where onDelete came from it was passed from the EmployeeList with the employee.

So a link to itself, an employee, and the onDelete method/function were passed, so that this is in the props when its needed.

The REST interface is called with DELETE requested, and a link to the employee, and then loadFromServer is called again to reload everything, and we end up back on the first page.

Paging On The React UI

In the tutorial it does discuss briefly re paging, and states that Spring Data Rest will automatically update the navigation links that are generated. The paging on the backend will be determined by the value passed back when we call the REST api. So in the loadFromServer() method, the size is passed as a parameter to the REST api.

The rest of the code related to the paging is about is in the UI app, setting the pagesize to be passed back to the REST api.

The EmployeeList has an input field for setting the pagesize

The handleInput() method validates the input field then, and calls the updatePageSize() method.

The updatePageSize() will call the loadFromServer() method to reload the page if the pagesize has changed.

Running the UI With Create and Delete Options

Here we see the resulting UI from the work we have done above when we run the app. (Dont forget to refresh your browser to load the updated code)

If we change the paging the number of rows shown updates immediately to reflect what we have entered.

If we delete a row that row disappears

If we click create, we get the new employee page popup, and we can fill in the details and create a new employee.

Updating Existing Resources With Spring Data Rest

So we have just learned how to create new employees and also to delete existing employees. But for full CRUD functionality of course we need to be able to update existing data.

The next thing that this Spring.oi Data Rest tutorial goes into is the discussion around the problem of performing updates. If I have access the list of employees, but then I go off and grab a coffee, someone else may also access the employee data from their PC, and update it. So now the data that im seeing on my screen is out of date, so if I come back to update it based on the data I have already loaded I could be wiping out the changes they have already made with my stale data.

To deal with such situations, the Javax Persistence API or JPA as its usually know, has a concept of versioning. Spring Data JPA has an implementation of JPA, and as Spring Data REST includes Spring Data JPA, we get those features included.

By adding a field to the data, that can be used to check if the data is stale, it will allow the application to reject the update if the data has already been updated. So lets look at how we put that all together.

Versioning Of Resources In The Rest Interface

To implement version, we need to create a field in our Employee domain object, and tag it so it is used for versioning. So in Employee.java the following is added

and heres the full version of Employee.java showing the version field

Every change in the Employee data will cause the version to be updated.

Rest and ETags

From the Spring documentation

An ETag (entity tag) is an HTTP response header returned by an HTTP/1.1 compliant web server used to determine change in content at a given URL.

https://docs.spring.io/spring/docs/3.0.0.M4/reference/html/ch15s11.html

From IETF

The “ETag” header field in a response provides the current entity-tag for the selected representation, as determined at the conclusion of handling the request. An entity-tag is an opaque validator for differentiating between multiple representations of the same resource, regardless of whether those multiple representations are due to resource state changes over time, content negotiation resulting in multiple representations being valid at the same time, or both.

https://tools.ietf.org/html/rfc7232#section-2.3

Basically an ETag is a hash of the response body that can be used to check for changes in the output. In our case we can use the Etag to ensure that we dont update our domain with stale data. When we grab an individual Employee, Spring Data Rest will automagically use the version to create an ETag for us in the response header. I have highlighted individual above, as currently we are retrieve the Employee data as a collection, which doesnt generate ETag, so we need to change the logic to retrieve the individual Employees.

So we need to modify our react code to that, so heres the updated app.js from the tutorial with the changes that are required.