Building Spring Boot, MongoDB and React.js CRUD Web Application

Building Spring Boot, MongoDB and React.js CRUD Web Application

Step by step tutorial on building Spring Boot 2.0.0, MongoDB and React.js CRUD Web Application

Step by step tutorial on building Spring Boot 2.0.0, MongoDB and React.js CRUD Web Application

Comprehensive step by step tutorial on building Spring Boot 2.0.0, MongoDB and React.js CRUD Web Application. Previously we have done a tutorial on building Spring Boot, MongoDB and Angular 5 CRUD Web Application. From there we have a lesson that integrates React.js or other front-end frameworks with Java web application is simple. We will run the React.js application on the same port as Spring Boot Java Web Application.

The following tools, frameworks, and modules are required for this tutorial achievement:

  • Java Development Kit 8
  • Spring Boot 2.0.0
  • Spring Web
  • Spring Data
  • Gradle
  • MongoDB
  • React.js
  • Node.js
  • Spring Initializer
  • Terminal or Command Line
  • Text Editor or IDE

Before continuing to the main steps, make sure that you have installed above tools, frameworks, and modules in your machine.

1. Generate Spring Boot 2.0.0 Web Application

As usual, we start creating Spring Boot 2.0.0 application by generating the application and its library using Spring Initializer. After go to Spring Initializer using the web browser, create the new application and add the library as below.

Click Generate Project button and the Spring boot 2.0.0 application will be downloaded by your browser. Next, extract the zipped Spring Boot project then copy or move to your Java projects folder. To run the Spring Boot application, type this command from the terminal or command line.

cd react
./gradlew bootRun

You will not find a landing page on the browser yet because of there’s no frontend or HTML page in the static folder. To connect Spring Boot with MongoDB, open and edit src/main/java/resources/application.properties then add this lines.

spring.data.mongodb.database=springreact
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017

Next, start MongoDB in the other terminal or command line if it’s not run yet. Run again Spring Boot application. Now, Spring Boot and MongoDB are connected and ready.

2. Create Java Model or Entity Class

If are using Text Editor, you have to create a folder for models. From the terminal create a models folder in src/main/java/com/djamware/react.

mkdir src/main/java/com/djamware/react/models

To create Model or Entity Class simply create a new file at src/main/java/com/djamware/react/models then name it Contact.java.

touch  src/main/java/com/djamware/react/models/Contact.java

Open and edit src/main/java/com/djamware/react/models/Contact.java then add this lines of codes.

package com.djamware.react.models;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "contacts")
public class Contact {
    @Id
    String id;
    String name;
    String address;
    String city;
    String phone;
    String email;

    public Contact() {
    }

    public Contact(String name, String address, String city, String phone, String email) {
        this.name = name;
        this.address = address;
        this.city = city;
        this.phone = phone;
        this.email = email;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

That class mapped to MongoDB collection with the name contacts.

3. Create a New Repository Interface for Contact Model

For connecting to Contact model, we need to create a Java interface or repository. Create a folder named repositories inside src/main/java/com/djamware/react/ folder.

mkdir src/main/java/com/djamware/react/repositories

Next, create a Java Interface file inside that folder.

touch src/main/java/com/djamware/react/repositories/ContactRepository.java

Open and edit src/main/java/com/djamware/react/repositories/ContactRepository.java then add this lines of codes of extended CrudRepository and only add a single method for delete contact.

package com.djamware.react.repositories;

import com.djamware.react.models.Contact;
import org.springframework.data.repository.CrudRepository;

public interface ContactRepository extends CrudRepository<Contact, String> {
    @Override
    void delete(Contact deleted);
}

We only add findOne and delete method to the interface because the rest method already handled by CrudRepository of Spring Data MongoDB.

4. Create a New Spring MVC RESTful Controller

Now, it's a time for RESTful Web Service (REST API) implementation by creating a new Spring MVC RESTful controller file. Create a folder named controllers inside src/main/java/com/djamware/react/ folder.

mkdir src/main/java/com/djamware/react/controllers

Create a Java file named ContactController.java inside that new folder.

touch src/main/java/com/djamware/react/controllers/ContactController.java

Open and edit src/main/java/com/djamware/react/controllers/ContactController.java then add this lines of codes that implementing request and response from or to the client-side using REST API. The REST API determine by @RestController and @RequestMapping Spring MVC annotation.

package com.djamware.react.controllers;

import com.djamware.react.models.Contact;
import com.djamware.react.repositories.ContactRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Optional;

@RestController
public class ContactController {

    @Autowired
    ContactRepository contactRepository;

    @RequestMapping(method=RequestMethod.GET, value="/contacts")
    public Iterable<Contact> contact() {
        return contactRepository.findAll();
    }

    @RequestMapping(method=RequestMethod.POST, value="/contacts")
    public Contact save(@RequestBody Contact contact) {
        contactRepository.save(contact);

        return contact;
    }

    @RequestMapping(method=RequestMethod.GET, value="/contacts/{id}")
    public Optional<Contact> show(@PathVariable String id) {
        return contactRepository.findById(id);
    }

    @RequestMapping(method=RequestMethod.PUT, value="/contacts/{id}")
    public Contact update(@PathVariable String id, @RequestBody Contact contact) {
        Optional<Contact> optcontact = contactRepository.findById(id);
        Contact c = optcontact.get();
        if(contact.getName() != null)
            c.setName(contact.getName());
        if(contact.getAddress() != null)
            c.setAddress(contact.getAddress());
        if(contact.getCity() != null)
            c.setCity(contact.getCity());
        if(contact.getPhone() != null)
            c.setPhone(contact.getPhone());
        if(contact.getEmail() != null)
            c.setEmail(contact.getEmail());
        contactRepository.save(c);
        return c;
    }

    @RequestMapping(method=RequestMethod.DELETE, value="/contacts/{id}")
    public String delete(@PathVariable String id) {
        Optional<Contact> optcontact = contactRepository.findById(id);
        Contact contact = optcontact.get();
        contactRepository.delete(contact);

        return "";
    }
}

5. Test The RESTful API

Now, re-run again Spring Boot application then test the REST API using CURL from the terminal.

./gradlew bootRun

Open another terminal then type this command to get a Contact list from the REST API.

curl -i -H "Accept: application/json" localhost:8080/contacts

It should display a response like this.

HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 05 Feb 2018 12:14:39 GMT

[]

To add a contact, type this command to post a contact data.

curl -i -X POST -H "Content-Type: application/json" -d '{"name":"John Doe","address":"Jl. Cipaganti No.112","city":"Bandung","phone":"0811223112233","email":"[email protected]"}' localhost:8080/contacts

It should display a response like this.

HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 06 Feb 2018 02:59:00 GMT

{"id":"5a7919f4b9d4f13c2cb6f539","name":"John Doe","address":"Jl. Cipaganti No.112","city":"Bandung","phone":"0811223112233","email":"[email protected]"}

You can check on MongoDB console to verify that new contact data is saved. Next, to get a single contact data by ID type this command.

curl -i -H "Accept: application/json" localhost:8080/contacts/5a784bbfb9d4f121d9a31195

And here’s the response.

HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 05 Feb 2018 12:22:49 GMT

{"id":"5a784bbfb9d4f121d9a31195","name":"John Doe","address":"Jl. Cipaganti No.112","city":"Bandung","phone":"0811223112233","email":"[email protected]"}

To update existing contact by ID type this command.

curl -i -X PUT -H "Content-Type: application/json" -d '{"name":"John Dodol"}' localhost:8080/contacts/5a784bbfb9d4f121d9a31195

It should response like this.

HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sat, 24 Mar 2018 08:49:11 GMT

{"id":"5a784bbfb9d4f121d9a31195","name":"John Dodol","address":"Jl. Cipaganti No.112","city":"Bandung","phone":"0811223112233","email":"[email protected]"}

To delete a contact by ID type this command.

curl -i -X DELETE localhost:8080/contacts/5a784bbfb9d4f121d9a31195

Here’s the response.

HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 0
Date: Sat, 24 Mar 2018 07:51:42 GMT

6. Create a React.js Application

This time for the frontend side, in the terminal and root project folder type this command.

create-react-app frontend

That command will create a React.js application folder named frontend. To make React build running as Spring Boot frontend, open and edit frontend/package.json then change build value in the scripts block as below.

"scripts": {
  "start": "react-scripts start",
  "build": "react-scripts build && rm -rf ../src/main/resources/static && mv build ../src/main/resources/static",
  "test": "react-scripts test --env=jsdom",
  "eject": "react-scripts eject"
},

Now, test the React.js configuration by type this command.

cd ./frontend
npm run build

Back to root folder then run again Spring Boot application.

cd ..
./gradlew bootRun

Now, when you pointing your browser to localhost:8080, you should see this page.

7. Add React Router DOM for CRUD Front End

This React front end consists of the Contacts list, detail, create and edit. For navigating between that component, we need to create a route. First, install modules that required by the components after stop the Spring Boot application.

cd ./frontend
npm install --save react-router-dom
npm install --save-dev bootstrap
npm install --save axios

Next, open and edit src/index.js then replace all codes with this.

iimport React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import App from './App';
import './App.css';
import Edit from './components/Edit';
import Create from './components/Create';
import Show from './components/Show';

ReactDOM.render(
  <Router>
      <div>
        <Route exact path='/' component={App} />
        <Route path='/edit/:id' component={Edit} />
        <Route path='/create' component={Create} />
        <Route path='/show/:id' component={Show} />
      </div>
  </Router>,
  document.getElementById('root')
);

You see that Edit, Create and Show added as the separate component. Bootstrap also included in the import for make the views better. Now, create the new edit, create and show files.

mkdir src/components
touch src/components/Create.js
touch src/components/Show.js
touch src/components/Edit.js

8. Add List of Contacts to Existing App Component

To get the list of Contacts and display to the page, open and edit frontend/src/App.js file then replace with these lines of codes which contain React App component that fetch data from REST API then display to HTML template as a List.

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Link } from 'react-router-dom';
import axios from 'axios';

class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      contacts: []
    };
  }

  componentDidMount() {
    axios.get('/contacts')
      .then(res => {
        this.setState({ contacts: res.data });
        console.log(this.state.contacts);
      });
  }

  render() {
    return (
      <div class="container">
        <div class="panel panel-default">
          <div class="panel-heading">
            <h3 class="panel-title">
              CONTACTS LIST
            </h3>
          </div>
          <div class="panel-body">
            <h4><Link to="/create"><span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span> Add Contact</Link></h4>
            <table class="table table-stripe">
              <thead>
                <tr>
                  <th>Name</th>
                  <th>Address</th>
                </tr>
              </thead>
              <tbody>
                {this.state.contacts.map(c =>
                  <tr>
                    <td><Link to={`/show/${c.id}`}>{c.name}</Link></td>
                    <td>{c.address}</td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>
        </div>
      </div>
    );
  }
}

export default App;

9. Add a Components for Create a New Contact

For add a new Contact, open and edit frontend/src/components/Create.js then replace all codes with this lines of codes.

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
import { Link } from 'react-router-dom';

class Create extends Component {

  constructor() {
    super();
    this.state = {
      name: '',
      address: '',
      city: '',
      phone: '',
      email: ''
    };
  }
  onChange = (e) => {
    const state = this.state
    state[e.target.name] = e.target.value;
    this.setState(state);
  }

  onSubmit = (e) => {
    e.preventDefault();

    const { name, address, city, phone, email } = this.state;

    axios.post('/contacts', { name, address, city, phone, email })
      .then((result) => {
        this.props.history.push("/")
      });
  }

  render() {
    const { name, address, city, phone, email } = this.state;
    return (
      <div class="container">
        <div class="panel panel-default">
          <div class="panel-heading">
            <h3 class="panel-title">
              ADD CONTACT
            </h3>
          </div>
          <div class="panel-body">
            <h4><Link to="/"><span class="glyphicon glyphicon-th-list" aria-hidden="true"></span> Contacts List</Link></h4>
            <form onSubmit={this.onSubmit}>
              <div class="form-group">
                <label for="isbn">Name:</label>
                <input type="text" class="form-control" name="name" value={name} onChange={this.onChange} placeholder="Name" />
              </div>
              <div class="form-group">
                <label for="title">Address:</label>
                <input type="text" class="form-control" name="address" value={address} onChange={this.onChange} placeholder="Address" />
              </div>
              <div class="form-group">
                <label for="author">City:</label>
                <input type="text" class="form-control" name="city" value={city} onChange={this.onChange} placeholder="City" />
              </div>
              <div class="form-group">
                <label for="published_date">Phone:</label>
                <input type="text" class="form-control" name="phone" value={phone} onChange={this.onChange} placeholder="Phone Number" />
              </div>
              <div class="form-group">
                <label for="publisher">Email:</label>
                <input type="email" class="form-control" name="email" value={email} onChange={this.onChange} placeholder="Email Address" />
              </div>
              <button type="submit" class="btn btn-default">Submit</button>
            </form>
          </div>
        </div>
      </div>
    );
  }
}

export default Create;

10. Add a Component for Show Contact Details

To show contact details that listed on the home page, open and edit frontend/src/components/Show.js then replace all codes with this lines of codes.

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

class Show extends Component {

  constructor(props) {
    super(props);
    this.state = {
      contact: {}
    };
  }

  componentDidMount() {
    axios.get('/contacts/'+this.props.match.params.id)
      .then(res => {
        this.setState({ contact: res.data });
        console.log(this.state.contact);
      });
  }

  delete(id){
    console.log(id);
    axios.delete('/contacts/'+id)
      .then((result) => {
        this.props.history.push("/")
      });
  }

  render() {
    return (
      <div class="container">
        <div class="panel panel-default">
          <div class="panel-heading">
            <h3 class="panel-title">
              Contact Details
            </h3>
          </div>
          <div class="panel-body">
            <h4><Link to="/"><span class="glyphicon glyphicon-th-list" aria-hidden="true"></span> Contacts List</Link></h4>
            <dl>
              <dt>Name:</dt>
              <dd>{this.state.contact.name}</dd>
              <dt>Address:</dt>
              <dd>{this.state.contact.address}</dd>
              <dt>City:</dt>
              <dd>{this.state.contact.city}</dd>
              <dt>Phone Number:</dt>
              <dd>{this.state.contact.phone}</dd>
              <dt>Email Address:</dt>
              <dd>{this.state.contact.email}</dd>
            </dl>
            <Link to={`/edit/${this.state.contact.id}`} class="btn btn-success">Edit</Link>&nbsp;
            <button onClick={this.delete.bind(this, this.state.contact.id)} class="btn btn-danger">Delete</button>
          </div>
        </div>
      </div>
    );
  }
}

export default Show;

In this component, there is two button for edit current contact and for delete current contact. Delete function included in this component.

11. Add a Component for Edit a Contact

After show contact details, we need to edit the contact. For that open and edit, frontend/src/components/Edit.jsthen add this lines of codes.

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

class Edit extends Component {

  constructor(props) {
    super(props);
    this.state = {
      contact: {}
    };
  }

  componentDidMount() {
    axios.get('/contacts/'+this.props.match.params.id)
      .then(res => {
        this.setState({ contact: res.data });
        console.log(this.state.contact);
      });
  }

  onChange = (e) => {
    const state = this.state.contact
    state[e.target.name] = e.target.value;
    this.setState({contact:state});
  }

  onSubmit = (e) => {
    e.preventDefault();

    const { name, address, city, postalCode, phone } = this.state.contact;

    axios.put('/contacts/'+this.props.match.params.id, { name, address, city, postalCode, phone })
      .then((result) => {
        this.props.history.push("/show/"+this.props.match.params.id)
      });
  }

  render() {
    return (
      <div class="container">
        <div class="panel panel-default">
          <div class="panel-heading">
            <h3 class="panel-title">
              EDIT Contact
            </h3>
          </div>
          <div class="panel-body">
            <h4><Link to={`/show/${this.state.contact.id}`}><span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span> Contact List</Link></h4>
            <form onSubmit={this.onSubmit}>
              <div class="form-group">
                <label for="name">Name:</label>
                <input type="text" class="form-control" name="name" value={this.state.contact.name} onChange={this.onChange} placeholder="Name" />
              </div>
              <div class="form-group">
                <label for="title">Address:</label>
                <input type="text" class="form-control" name="address" value={this.state.contact.address} onChange={this.onChange} placeholder="Address" />
              </div>
              <div class="form-group">
                <label for="author">City:</label>
                <input type="text" class="form-control" name="city" value={this.state.contact.city} onChange={this.onChange} placeholder="City" />
              </div>
              <div class="form-group">
                <label for="published_date">Phone Number:</label>
                <input type="text" class="form-control" name="phone" value={this.state.contact.phone} onChange={this.onChange} placeholder="Phone Number" />
              </div>
              <div class="form-group">
                <label for="description">Email:</label>
                <input type="email" class="form-control" name="email" value={this.state.contact.email} onChange={this.onChange} placeholder="Email Address" />
              </div>
              <button type="submit" class="btn btn-default">Update</button>
            </form>
          </div>
        </div>
      </div>
    );
  }
}

export default Edit;

12. Run and Test Spring Boot 2.0.0, MongoDB and React.js CRUD Web Application

It’s time for running the server and client side and test all CRUD functionality. Type this command to build the React.js application and deploy to Spring Boot 2.0.0 application.

npm run build

Now, back to the root directory then type this command to run again Spring Boot 2.0.0 application.

cd ..
./gradlew bootRun

Here the whole application looks like.

That’s it, a simple CRUD application build by Spring Boot 2.0.0, MongoDB and React.js. You can compare with the full working source code from our GitHub.

That just the basic. If you need more deep learning about Java and Spring Framework you can take the following cheap course:

Originally published by** Didin J** at **https://www.djamware.com

=====================================================================

Thanks for reading :heart: If you liked this post, share it with all of your programming buddies! Follow me on Facebook | Twitter

mongodb reactjs spring-boot

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Spring Boot, Security, MVC, Data and MongoDB Login Example

Creating the authentication (login) using Spring Boot, Spring Security, Spring Data and MongoDB for Java web application with custom User Details Service. Spring Security is one of the most used Security frameworks for Java Web Application.

Build Web App Authentication using Spring Boot, Spring Security, MongoDB and Angular 8

In this article, you'll learn how to build web application authentication using Spring Boot, Spring Security, MongoDB, and Angular 8

Spring Boot Tutorials - Spring Boot Full Course

Spring Boot Tutorials | Full Course - What is Spring? Spring Boot is an open source Java-based framework used to create a Micro Service. Spring Boot contains a comprehensive infrastructure support for developing a micro service and enables you to develop enterprise-ready applications that you can “just run”.

Build a Reactive App with Spring Boot and MongoDB

This tutorial shows how to build a non-blocking, reactive app with Spring Boot, Spring WebFlux, and MongoDB

Spring vs Spring Boot

We will see how Spring and Spring Boot can be compared. Programmers need not start from scratch when they want to work on some projects.