Spring Boot and React: Happily Ever After

Matt McCandless Problem Solving, React, Spring Boot, Technology Snapshot Leave a Comment

So you have mastered Spring Boot and started toying around with React. Now you want React to talk to your Boot app as your back-end API. That’s fabulous. You probably already know how to do this, but there is a kicker. You want to package them and start both of them as just one project.

Well, you’re in luck! This blog is going to take a couple of simple projects and combine them into one project. Lace up your boots and get ready to React!

Wedding Boots

First off we have to get the Spring Boot app up and running. Here are the steps. All these steps are using the STS IDE. In my opinion, when working on Boot it is easiest to use the tool recommended by Spring. If you are an IntelliJ user or something else, feel free to do what you like. If you already have an application you would like to use, then skip this section.

  1. Create a New > Spring Starter Project
  2. Give your project a name. Then select if you want Gradle or Maven. We’ll use Maven for this article.
  3. Next, we’ll choose “Web” and “Jersey”. This keeps what we want to do really simple. There are no database needs at this point or any other shenanigans.After the build, it should look something like this.
  4. We will create a Model object for our JSON object.
    public class Message {
       	
       	private String name;
       	
       	public Message(String name) {
              	this.name = name + ", thanks so much for clicking the button! You really do love me!";
       	}
     
       	public String getName() {
              	return name;
       	}
     
       	public void setName(String name) {
              	this.name = name;
       	}
     
    }
    
  5. Next, add New Java Class we’ll call DemoRestController. Paste this in
import com.example.model.Message;
 
@RestController
public class DemoRestController {
   	
   	@RequestMapping("/greeting")
	public Message greeting(@RequestParam(value="name", defaultValue="World") String name) {
    	return new Message(name);
	}
 
}

Alright, we’ve done what we need to do from a Spring Boot perspective.

Be sure that the Boot Project runs. From STS you can use the Boot Dashboard and just run it, or you can click on the then right click and choose “Run as Java Application”. Also if using Maven, you can use mvn spring-boot:run. Check http://localhost:8080?name=Bob. It should produce a JSON object.

{"name":"John, thanks so much for clicking the button…"}

React to Love

  • Have NPM and yarn installed.
  • Open a command line and navigate to BootReactStarter directory and run yarn create react-app frontend
  • Grab a cold one and wait for everything to install. It’ll take a bit.
See Also:  Gaining Docker Image Size Efficiencies By Separating Application Layers

When it is done, you should see something like this:

So let’s do what it says!

A browser window should load to http://localhost:3000 and give you the basic React page like so:

It is time to make a couple of adjustments. In the frontend directory, change the package.json file. We will be adding a “proxy” so that any requests we add will go to http://localhost:8080 (our Spring boot app).

`"proxy": "http://localhost:8080",`

Restart the React application.

Next we’ll add in an input box and button to demonstrate our call to the API. Paste this into App.js:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
 
class App extends Component {
  state = {
	isLoading: false,
	greeting: ""
  };
 
  sayHello = async (event) => {
    event.preventDefault();
	let response = await fetch('/greeting?name=' + this.state.greeting);
	let body = await response.json();
	this.setState({ greeting: body.name, isLoading: false, isGreetingVisible: '' });
  }
 
  updateName = (event) => {
    event.preventDefault();
    this.setState({greeting: event.target.value, isLoading: false});
  }
 
  render() {
	const {greeting, isLoading} = this.state;
 
	if (isLoading) {
  	return 

Loading...

;
	}
 
	return (
  	
<div className="App">
    	
<header className="App-header">
      	<img src={logo} className="App-logo" alt="logo" />
      	
<div className="App-intro">
        	<input onChange={(event)=>this.updateName(event)} placeholder="Enter Your Name"></input>
        	<button onClick={(event)=>this.sayHello(event)}>Please Click Me!</button>
        	
<h2 style={{visibility: this.isGreetingVisible}}>Hello {this.state.greeting}</h2>

            
      	</div>

        </header>

  	</div>

	);
  }
}
 
export default App;`

If you’re already running the React server, it will automatically reload. Otherwise, start it again.

With both React and Boot running, fill in a name and click the button. It should look something like this.

The click of the button makes a request to our Boot back end and returns a string appended to the name entered. This is a simplistic request, but it demonstrates how the two can work together.

Awesome, well done! Now it’s time to marry the two together. We need to change the pom.xml by adding in these values:

<properties>
…
   	<frontend-maven-plugin.version>1.6</frontend-maven-plugin.version>
   	<node.version>v10.13.0</node.version>
   	<yarn.version>v1.12.1</yarn.version>
…
</properties>

And adding in profiles:

<profiles>
   	    <profile>
   	        <id>dev</id>
   	        <activation>
   	        	<activeByDefault>true</activeByDefault>
   	        </activation>
   	        <properties>
   	        	<spring.profiles.active>dev</spring.profiles.active>
   	        </properties>
   	    </profile>
   	    <profile>
   	        <id>prod</id>
   	        <build>
   	        	<plugins>
   	            	<plugin>
   	                	<artifactId>maven-resources-plugin</artifactId>
   	                	<executions>
   	                    	<execution>
   	                        	<id>copy-resources</id>
   	                        	<phase>process-classes</phase>
   	                        	<goals>
   	                            	<goal>copy-resources</goal>
   	                        	</goals>
   	                        	<configuration>
   	          	                  <outputDirectory>${basedir}/target/classes/static</outputDirectory>
   	                            	<resources>
   	                                	<resource>
   	                                    	<directory>frontend/build</directory>
   	                                	</resource>
   	                            	</resources>
   	                        	</configuration>
   	                    	</execution>
   	                	</executions>
   	            	</plugin>
   	            	<plugin>
   	                	<groupId>com.github.eirslett</groupId>
   	                	<artifactId>frontend-maven-plugin</artifactId>
   	                	<version>${frontend-maven-plugin.version}</version>
   	                	<configuration>
   	                    	<workingDirectory>frontend</workingDirectory>
   	                	</configuration>
   	                	<executions>
   	                    	<execution>
   	                        	<id>install node</id>
   	                        	<goals>
   	                            	<goal>install-node-and-yarn</goal>
   	                        	</goals>
   	                        	<configuration>
   	                            	<nodeVersion>${node.version}</nodeVersion>
   	                            	<yarnVersion>${yarn.version}</yarnVersion>
   	                        	</configuration>
   	                    	</execution>
   	                    	<execution>
   	                        	<id>yarn install</id>
   	                        	<goals>
   	                            	<goal>yarn</goal>
   	                        	</goals>
   	                        	<phase>generate-resources</phase>
   	                    	</execution>
   	                    	<execution>
   	                        	<id>yarn test</id>
   	                        	<goals>
   	                            	<goal>yarn</goal>
   	                        	</goals>
   	                        	<phase>test</phase>
   	                        	<configuration>
   	                            	<arguments>test</arguments>
   	                            	<environmentVariables>
   	                                	<CI>true</CI>
   	                            	</environmentVariables>
   	                        	</configuration>
   	                    	</execution>
   	                    	<execution>
   	                        	<id>yarn build</id>
   	                        	<goals>
   	                            	<goal>yarn</goal>
   	                        	</goals>
   	                        	<phase>compile</phase>
   	                        	<configuration>
   	                            	<arguments>build</arguments>
   	                        	</configuration>
   	                    	</execution>
   	                	</executions>
   	            	</plugin>
   	        	</plugins>
   	        </build>
   	        <properties>
   	        	<spring.profiles.active>prod</spring.profiles.active>
   	        </properties>
   	    </profile>
   	</profiles>
 

Make sure you have stopped both React and Boot if they were running individually. Go back to your command line and start with the following:

`mvnw spring-boot: run -Pprod`

This will again take some time as it is packaging everything up into one file. It will download everything again so you can go water the garden or get some pretzels to go with that cold one you picked up.

See Also:  Quick Start: AWS SQS + Spring Boot Processing FIFO Queues

Once it is up and running, open a browser and go to http://localhost:8080. Your React app should be displayed. Ouila! You have run your React app via Spring Boot.

Conclusion

We have created a standalone Spring Boot application and a standalone React application. Once they were working on their own, we put them together into one runnable jar. This can make deployment onto whatever system a breeze.

This project is far from a Production-ready release, but you can see how easy this can make development when dealing with both of these game-changing technologies. Have fun developing as a full-stack developer!

References:

What Do You Think?