Creating a Full Stack Web Application with Spring Boot and Next js
Learn to build a full-stack web app with Spring Boot and Next.js. In this blog post, we will cover the step-by-step process of building a web application using Next.js and Spring Boot. We'll explore various topics, including configuring Next.js as a static site with a Spring Boot backend, integrating Next.js and Spring Boot in a single app server, setting up proxy server settings in Next.js, and leveraging application plugins in a Spring Boot application.
Here are some of the topics covered.
Configuring Next.js as a Static Site with a Spring Boot Backend.
Integrating Next.js and Spring Boot in a Single App Server.
Next.js Proxy Server Settings for development purposes.
Application Plugins with Spring Boot App.
Next.js Proxy Server Settings without Cross-Domain Proxy Settings for dev.
Build a Spring Boot Application with Application Plugins in Gradle.
Gralde with Spring Boot for production.
Environment and Tools
Java | 17 |
Spring Boot | 3.1.1 |
NextJs | 13.4.10 |
React | 18.2.0 |
Gradle | 8.1.1 |
Node | 16.17.1 |
npm | 8.15.0 |
Frontend Setup with Next.js
Create a Next.js App
To start, open your desired directory and run the following command to create the front-end of your application:
npx create-next-app@latest
This command sets up a new Next.js project with the latest version, providing you with a solid foundation for building the front end.
Open the Next.js Project in VS Code
Once the Next.js project is created, open it in your preferred text editor, such as Visual Studio Code. This will allow you to work with the front-end code and make necessary modifications.
Update the package.json File
In the Next.js project, locate the package.json file and update it with any additional dependencies or scripts specific to your application. This file manages the project's dependencies and configuration.
{
"name": "nextjs-spring-app",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build && next export",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"eslint": "8.44.0",
"eslint-config-next": "13.4.10",
"next": "13.4.10",
"react": "18.2.0",
"react-dom": "18.2.0"
}
}
Modify the next.config.js File
Configure your Next.js application by modifying the next.config.js file. This file allows you to define custom settings, configure routing, and perform other project-specific configurations.
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
images: {
unoptimized: true,
},
async rewrites() {
return [
{
source: '/e3docs/:path*',
destination: 'http://localhost:8080/e3docs/:path*',
},
]
},
}
module.exports = nextConfig
Fetch Data from the Backend
Create a list.js file in the Next.js project responsible for fetching data from the Spring Boot API. Implement the necessary logic to retrieve data from the backend and render it in the frontend.
list.js
import Link from 'next/link';
import { Fragment, useEffect, useState } from 'react';
function List() {
const [list, setList] = useState([])
const fetchList = () => {
fetch("/e3docs/getlist")
.then(response => {
return response.json()
})
.then(data => {
setList(data)
})
}
useEffect(() => {
fetchList()
}, [])
function getlist() {
return list.map((item, i) => {
return (
<Fragment key={i}>
<tr>
<td>
{(i + 1)}
</td>
<td>
{item}
</td>
</tr>
</Fragment>
);
})
}
return (
<main>
<div style={{ paddingLeft: '34%', paddingTop: '2%', display: 'flex' }}>
<h2 style={{ paddingRight: '10px' }}>
<Link href="/">Home</Link>
</h2>
<h2>
<Link href="/list">List</Link>
</h2>
</div>
<div style={{ paddingLeft: '34%', paddingTop: '3%' }}>
<table>
<thead>
<tr>
<th>No.</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{list.length > 0 && (getlist())}
</tbody>
</table >
</div>
</main>
);
}
export default List;
Modify index.js and Add List Mapping
In the Next.js project, modify the index.js file and add a mapping for the list page using the Link tag. This will enable users to navigate to the list page and view the data fetched from the backend.
index.js
import Head from 'next/head'
import Image from 'next/image'
import Link from 'next/link'
export default function Home() {
return (
<>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main>
<div style={{ paddingLeft: '34%', paddingTop: '2%', display: 'flex' }}>
<h2 style={{ paddingRight: '10px' }}>
<Link href="/">Home</Link>
</h2>
<h2>
<Link href="/list">List</Link>
</h2>
</div>
<div style={{ paddingLeft: '34%', paddingTop: '3%' }}>
<Image
src="/next.svg"
alt="Next.js Logo"
width={180}
height={37}
priority
/>
<Image
src="/Spring_Logo.svg"
alt="Spring Logo"
width={200}
height={45}
priority
/>
</div>
</main>
</>
)
}
Create a New Page to Handle Web App Refresh and Direct URL Entry
To handle scenarios like web app refresh or direct URL entry, create a new page in the Next.js project. This page will help to handle the 404 error page in Next JS when the user enters a direct URL into the browser or the page refreshes.
pagerefresh.js
import { useRouter } from 'next/router';
import { useEffect } from 'react';
function PageRefresh() {
const router = useRouter();
useEffect(() => {
if (router.isReady) {
router.push(router.asPath).catch((e) => {
router.push('/_error');
});
}
}, [router.isReady])
return (
<div>Loading...</div>
);
}
export default PageRefresh;
Build and Export the Next.js Project
To generate the static content for deployment, run the following command in your Next.js project:
npm run build
This will create an "out" folder with the compiled and optimized Next.js application.
Backend Setup with Spring Boot
Create a New Project with Spring Initializr
Use Spring Initializr to create a new Spring Boot project. Specify the necessary dependencies and project settings, and generate the project structure.
Update the build.gradle File
After generating the project, locate the build.gradle file and update it with any additional dependencies or plugins required for your application. This file serves as the configuration for your build system.
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.1'
id 'io.spring.dependency-management' version '1.1.0'
id 'eclipse'
id 'application'
}
group = 'com.e3docs'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-rest'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
application {
mainClass = 'com.e3docs.SpringBootAndNextJsApplication'
applicationDefaultJvmArgs = ['-Dfile.encoding=UTF-8']
bootDistZip.enabled = false
bootDistTar.enabled = false
distTar.enabled = false
bootJar.enabled = false
executableDir = ""
}
Build the Project for Eclipse
Prepare the project for Eclipse by running the following command in your project directory:
gradlew clean cleanEclipse build eclipse
This command cleans the project, builds it, and generates Eclipse-specific files for smooth integration with the IDE.
Import the Project into Eclipse
Once the command from the previous step is completed successfully, import the project into Eclipse as an existing project. This allows you to leverage the powerful features of Eclipse for development.
Create a Controller Class for API
To handle API requests, create a controller class in your Spring Boot project. This class will define the endpoints and their associated request-handling methods, allowing you to interact with your backend API.
package com.e3docs.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("e3docs")
public class E3DocsController {
@GetMapping("/getlist")
public List<String> getList() {
List<String> list = new ArrayList<String>();
list.add("India");
list.add("China");
list.add("United States(US)");
list.add("Russia");
list.add("Australia");
list.add("African");
list.add("Europe");
return list;
}
}
Create a Filter Component for Next.js Integration
For smooth integration between the Spring Boot backend and the Next.js frontend, create a filter component. This component will intercept requests and perform necessary actions like direct URL entry or page refresh.
package com.e3docs.config;
import java.io.IOException;
import org.springframework.stereotype.Component;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@Component
public class PageRefreshFilter implements Filter {
private static final String PAGE = "/pagerefresh/pagerefresh.html";
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
doFilter((HttpServletRequest) request, (HttpServletResponse) response, chain);
}
private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
String path = request.getServletPath();
if ("/".equals(path) || path.contains(".") || path.contains("e3docs")) {
chain.doFilter(request, response);
} else {
request.getRequestDispatcher(PAGE).forward(request, response);
}
}
}
Integrate the Frontend with the Backend
Copy the static content from the "out" folder of the Next.js project into the Spring Boot project's /src/main/resources/static folder. This ensures that the frontend assets are accessible from the Spring Boot server.
Build the Backend Project
Build the Spring Boot project by running the following command:
gradlew clean assemble
After a successful build, you will find a zip file in the build/distributions folder.
Run the Application
Extract the zip file and run the appropriate script (e.g., bat file) to start the Spring Boot server.
Once the server is up and running, access the application by navigating to http://localhost:8080 in your web browser.
Congratulations! You have successfully learned how to create a full-stack web application using Spring Boot and Next.js. By following the steps outlined in this guide, you now have the knowledge and tools to build robust and modern web applications. With Spring Boot powering the backend and Next.js handling the front end, you can leverage the strengths of both frameworks to deliver an exceptional user experience.
Happy coding!