Vue.js + Spring Boot + MongoDB - CRUD example

Hello everyone, today we will learn how to build a full-stack application that is a basic User Management Application using Spring Boot, MongoDB, and Vue.js.GitHub repository link is provided at the end of this tutorial. You can download the source code.



  • Spring boot is used to develop REST web services and microservices. Spring Boot has taken the Spring framework to the next level. It has drastically reduced the configuration and setup time required for spring projects. We can set up a project with almost zero configuration and start building the things that actually matter to your application.
  • Vue.js is an open-source model–view–ViewModel front-end JavaScript framework for building user interfaces and single-page applications.

After completing this tutorial what we will build?

We will build a full-stack web application that is a basic User Management Application with CRUD features:

    • Create User
    • List User
    • Update User
    • Delete User

Following is the screenshot of our application -

-Retrieve all Users:


-Add a User:


-Update User:


We divided this tutorial into two parts

PART 1 - Rest APIs Development using Spring Boot
PART 2 - UI development using Vue.js

PART 1 - Rest APIs Development using Spring Boot

These are APIs that the Spring Boot application will export: 

  1. GET all User's        :     /api/v1/users
  2. GET User by ID     :     /api/v1/users/{_id}
  3. POST User             :     /api/v1/users 
  4. PUT User               :     /api/v1/users/{_id} 
  5. DELETE User       :     /api/v1/users/{_id}

Back end project structure



pom.xml 

Include spring-boot-starter-web for Spring MVC and REST structure, spring-boot-starter-data-MongoDB for CRUD repository.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>backend-springboot-mongoDB</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>backend-springboot-mongoDB</name>
<description>Demo project for Spring Boot</description>

<properties>
<java.version>11</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>


application.properties

spring.data.mongodb.uri=mongodb://localhost:27017/user-dev
server.port=8081


Repository[UserRepository.java]

@Repository is a Spring annotation that designates that the adorned interface is a repository. A repository is a mechanism for encapsulating storage, retrieval, and search comportment which emulates a collection of objects.
package com.knf.dev.repository;

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import com.knf.dev.document.User;

@Repository
public interface UserRepository extends MongoRepository<User, String> {

}


Document[User.java]


@Document to identify a domain object to be persisted to MongoDB.
package com.knf.dev.document;

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

@Document(collection = "database_sequences")
public class User {

private String _id;
private String firstName;
private String lastName;
private String emailId;

public String getId() {
return _id;
}

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

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getEmailId() {
return emailId;
}

public void setEmailId(String emailId) {
this.emailId = emailId;
}

public User(String _id, String firstName, String lastName,
String emailId) {
super();
this._id = _id;
this.firstName = firstName;
this.lastName = lastName;
this.emailId = emailId;
}

public User() {
super();
}
}


ResourceNotFoundException.java

package com.knf.dev.ResourceNotFoundException;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends Exception {

private static final long serialVersionUID = 1L;

public ResourceNotFoundException(String message) {
super(message);
}
}


RestController [UserController.java]

Spring @RestController annotation is a convenience annotation that is itself annotated with @Controller and @ResponseBody. Spring RestController annotation is utilized to engender RESTful web services utilizing Spring MVC. Spring RestController takes care of mapping request data to the defined request handler method.
package com.knf.dev.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.knf.dev.ResourceNotFoundException.ResourceNotFoundException;
import com.knf.dev.document.User;
import com.knf.dev.repository.UserRepository;

@RestController
@RequestMapping("/api/v1")
public class UserController {
@Autowired
private UserRepository userRepository;

@GetMapping("/users")
public List<User> getAllUsers() {
return userRepository.findAll();
}

@GetMapping("/users/{id}")
public ResponseEntity<User> getUserById(@PathVariable(value = "id")
String id) throws ResourceNotFoundException {
User user = userRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException
("User not found for this id :: " + id));
return ResponseEntity.ok().body(user);
}

@PostMapping("/users")
public User createUser(@Valid @RequestBody User user) {
return userRepository.save(user);
}

@PutMapping("/users/{id}")
public ResponseEntity<User> updateUser(@PathVariable(value = "id")
String id, @Valid @RequestBody User userDto)
throws ResourceNotFoundException {
User user = userRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException
("User not found for this id :: " + id));

user.setEmailId(userDto.getEmailId());
user.setLastName(userDto.getLastName());
user.setFirstName(userDto.getFirstName());
user.setId(id);
final User updateUser = userRepository.save(user);
return ResponseEntity.ok(updateUser);
}

@DeleteMapping("/users/{_id}")
public Map<String, Boolean> deleteUser(@PathVariable(value = "_id")
String id) throws ResourceNotFoundException {
User user = userRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException
("User not found for this id :: " + id));

userRepository.delete(user);
Map<String, Boolean> response = new HashMap<>();
response.put("deleted", Boolean.TRUE);
return response;
}
}


Spring Boot Main class [SpringbootAngularMongodbCrudApplication.java]

package com.knf.dev;

import java.util.Arrays;
import java.util.Collections;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@SpringBootApplication
public class SpringbootAngularMongodbCrudApplication {

public static void main(String[] args) {
SpringApplication.run(SpringbootAngularMongodbCrudApplication.class,
args);
}

@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source =
new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
// Don't do this in production, use a proper list of allowed origins
config.setAllowedOrigins(Collections.singletonList("*"));
config.setAllowedHeaders(Arrays.asList("Origin",
"Content-Type", "Accept"));
config.setAllowedMethods(Arrays.asList("GET", "POST",
"PUT", "OPTIONS", "DELETE", "PATCH"));
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}


Github repository download link is provided at the end of this tutorial

Local Setup:

Step 1: Download or clone the source code to a local machine.

Spring Boot - Backend Project Setup

Step 2mvn clean install

Step 3: Run the Spring Boot application
mvn spring-boot:run


PART 2 - UI development using Vue.js


Package structure - Front end


package.json

A package.json is a JSON file that subsists at the root of a Javascript/Node project. It holds metadata pertinent to the project and is utilized for managing the project's dependencies, scripts, version, and a whole lot more.
{
"name": "frontend-vuejs",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.18.0",
"vue": "^2.6.6",
"vue-router": "^3.0.2"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.5.0",
"@vue/cli-plugin-eslint": "^3.5.0",
"@vue/cli-service": "^3.5.0",
"babel-eslint": "^10.0.1",
"eslint": "^5.8.0",
"eslint-plugin-vue": "^5.0.0",
"vue-template-compiler": "^2.5.21"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"rules": {},
"parserOptions": {
"parser": "babel-eslint"
}
},
"postcss": {
"plugins": {
"autoprefixer": {}
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}


Components

Vue Components are one of the important features of VueJS that creates custom elements, which can be reused in HTML

User.vue

<template>
<div>
<h3>User</h3>
<div class="container">
<form @submit="validateAndSubmit">
<div v-if="errors.length">
<div
class="alert alert-danger"
v-bind:key="index"
v-for="(error, index) in errors"
>
{{ error }}
</div>
</div>
<fieldset class="form-group">
<label>First Name</label>
<input type="text" class="form-control" v-model="firstName" />
</fieldset>
<fieldset class="form-group">
<label>Last Name</label>
<input type="text" class="form-control" v-model="lastName" />
</fieldset>
<fieldset class="form-group">
<label>Email Id</label>
<input type="text" class="form-control" v-model="emailId" />
</fieldset>
<button class="btn btn-success" type="submit">Save</button>
</form>
</div>
</div>
</template>
<script>
import UserDataService from "../service/UserDataService";

export default {
name: "User",
data() {
return {
firstName: "",
lastName: "",
emailId: "",
errors: [],
};
},
computed: {
id() {
return this.$route.params.id;
},
},
methods: {
refreshUserDetails() {
UserDataService.retrieveUser(this.id).then((res) => {
this.firstName = res.data.firstName;
this.lastName = res.data.lastName;
this.emailId = res.data.emailId;
});
},
validateAndSubmit(e) {
e.preventDefault();
this.errors = [];
if (!this.firstName) {
this.errors.push("Enter valid values");
} else if (this.firstName.length < 5) {
this.errors.push("Enter atleast 5 characters in First Name");
}
if (!this.lastName) {
this.errors.push("Enter valid values");
} else if (this.lastName.length < 5) {
this.errors.push("Enter atleast 5 characters in Last Name");
}
if (this.errors.length === 0) {
if (this.id == -1) {
UserDataService.createUser({
firstName: this.firstName,
lastName: this.lastName,
emailId: this.emailId,
}).then(() => {
this.$router.push("/users");
});
} else {
UserDataService.updateUser(this.id, {
id: this.id,
firstName: this.firstName,
lastName: this.lastName,
emailId: this.emailId,
}).then(() => {
this.$router.push("/users");
});
}
}
},
},
created() {
this.refreshUserDetails();
},
};
</script>


Users.vue

<template>
<div class="container">
<h3>All Users</h3>
<div v-if="message" class="alert alert-success">{{ this.message }}</div>
<div class="container">
<table class="table">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email Id</th>
<th>Update</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<tr v-for="user in users" v-bind:key="user.id">
<td>{{ user.firstName }}</td>
<td>{{ user.lastName }}</td>
<td>{{ user.emailId }}</td>
<td>
<button class="btn btn-warning" v-on:click="updateUser(user.id)">
Update
</button>
</td>
<td>
<button class="btn btn-danger" v-on:click="deleteUser(user.id)">
Delete
</button>
</td>
</tr>
</tbody>
</table>
<div class="row">
<button class="btn btn-success" v-on:click="addUser()">Add</button>
</div>
</div>
</div>
</template>
<script>
import UserDataService from "../service/UserDataService";

export default {
name: "Users",
data() {
return {
users: [],
message: "",
};
},
methods: {
refreshUsers() {
UserDataService.retrieveAllUsers().then((res) => {
this.users = res.data;
});
},
addUser() {
this.$router.push(`/user/-1`);
},
updateUser(id) {
this.$router.push(`/user/${id}`);
},
deleteUser(id) {
UserDataService.deleteUser(id).then(() => {
this.refreshUsers();
});
},
},
created() {
this.refreshUsers();
},
};
</script>


UserDataService.js

import axios from 'axios'

const USER_API_URL = 'http://localhost:8081/api/v1'

class UserDataService {

retrieveAllUsers() {
return axios.get(`${USER_API_URL}/users`);
}

retrieveUser(id) {
return axios.get(`${USER_API_URL}/users/${id}`);
}

deleteUser(id) {
return axios.delete(`${USER_API_URL}/users/${id}`);
}

updateUser(id, user) {
return axios.put(`${USER_API_URL}/users/${id}`, user);
}
createUser(user) {
return axios.post(`${USER_API_URL}/users`, user);
}
}
export default new UserDataService()


App.vue

<template>
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="#"
>Spring Boot + Mongo DB + Vue.js CRUD Application</a
><br /><br />
</div>
<router-view />
</div>
</template>

<script>
export default {
name: "app",
};
</script>

<style>
@import
url(https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css);
</style>


routes.js

import Vue from "vue";
import Router from "vue-router";

Vue.use(Router);

const router = new Router({
mode: 'history',
routes: [
{
path: "/",
name: "Users",
component: () => import("./components/Users"),
},
{
path: "/users",
name: "Users",
component: () => import("./components/Users"),
},
{
path: "/user/:id",
name: "User",
component: () => import("./components/User"),
},
]
});

export default router;


main.js

import Vue from 'vue'
import App from './App.vue'
import router from './routes';

Vue.config.productionTip = false

new Vue({
router,
render: h => h(App),
}).$mount('#app')


Vue JS - Frontend Project Setup

Step 1: The npm install installs all modules that are listed on package.json file and their
dependencies
npm install
Step 2: Run the Frontend application
npm run serve
 App running at:

Download source code -click here



More related topics,

Popular posts from this blog

Spring boot video streaming example-HTML5

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Spring Boot + Mockito simple application with 100% code coverage

Spring Boot + OpenCSV Export Data to CSV Example

Custom Exception Handling in Quarkus REST API

DataTable-Pagination example with Spring boot, jQuery and ajax

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Node JS mini projects with source code - free download

Spring boot web project free download:User Registration System

Java - Blowfish Encryption and decryption Example