java, get set methods

This question has been asked before, but even after reading:

This question has been asked before, but even after reading:

Java "Get" and "Set" Methods

Java Get/Set method returns null

And more I still don't understand how to solve my problem.

When accessing variables in a class using get methods from another class I receive the value null.

How do I recieve my correct values instead of null?

This is the class where I try to get my variables FROM (not everything included).

public class RLS_character_panel extends javax.swing.JPanel implements ActionListener, ItemListener { 
private String name1 = "hello"; 

public String getName1() { 
    return name1; 
} 

public void setName1(String name1) { 
    this.name1 = name1; 
} 

}

This is the class where i try to get the values TO. This class extends JFrame so that I can add a JPanel which displays the variable. (the JPanel is yet another class called: RLS_strid_panel , which is added upon this frame).

public class RLS_strid_java extends JFrame {

RLS_character_panel test = new RLS_character_panel(); 

String name1 = test.getName1(); 

RLS_strid_panel p = new RLS_strid_panel(namn1); 

// constructor
public RLS_strid_java(String titel) { 
    super(titel); 
    this.setSize(1000, 772); 
    this.setVisible(true); 
    this.setResizable(false); 
    this.add(p); 
} 

}

the Jpanel Displays null.

Angular 7 + Spring Boot CRUD Example

Angular 7 + Spring Boot CRUD Example

In this tutorial we will be implementing CRUD operations using Angular 7 + Spring Boot.

In this tutorial we will be implementing CRUD operations using Angular 7 + Spring Boot.

In previous tutorial we had implemented - Angular 7 + Spring Boot Hello World Example. We exposed REST endpoint using Spring Boot and consumed this endpoint using Angular 7 application and displayed the data.

In this tutorial we will be implementing CRUD operations using Angular 7 + Spring Boot. We will also be adding the header with menu and footer to our application. So following will be the components on our page.

Angular 7 + Spring Boot CRUD Demo

Angular 7 + Spring Boot Application Hello World Example

Angular 7 + Spring Boot Application CRUD Example

Angular 7 + Spring Boot Application Login Example

The code we had developed in previous application for Angular 7 + Spring Boot Application Hello World Example will be the starting point for this tutorial.

Spring Boot Application

Previous application we had created a simple spring boot application which exposed a REST endpoint for fetching a list of employees. In this tutorial we will be adding 2 more REST endpoints - One for creating an employee and other for deleting it.

package com.javainuse.controllers;

import java.util.ArrayList;
import java.util.List;

import org.springframework.web.bind.annotation.CrossOrigin;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.javainuse.model.Employee;

@CrossOrigin(origins = "http://localhost:4200")
@RestController
@RequestMapping({ "/employees" })
public class TestController {

	private List<Employee> employees = createList();

	@GetMapping(produces = "application/json")
	public List<Employee> firstPage() {
		return employees;
	}

	@DeleteMapping(path = { "/{id}" })
	public Employee delete(@PathVariable("id") int id) {
		Employee deletedEmp = null;
		for (Employee emp : employees) {
			if (emp.getEmpId().equals(id)) {
				employees.remove(emp);
				deletedEmp = emp;
				break;
			}
		}
		return deletedEmp;
	}

	@PostMapping
	public Employee create(@RequestBody Employee user) {
		employees.add(user);
		System.out.println(employees);
		return user;
	}

	private static List<Employee> createList() {
		List<Employee> tempEmployees = new ArrayList<>();
		Employee emp1 = new Employee();
		emp1.setName("emp1");
		emp1.setDesignation("manager");
		emp1.setEmpId("1");
		emp1.setSalary(3000);

		Employee emp2 = new Employee();
		emp2.setName("emp2");
		emp2.setDesignation("developer");
		emp2.setEmpId("2");
		emp2.setSalary(3000);
		tempEmployees.add(emp1);
		tempEmployees.add(emp2);
		return tempEmployees;
	}

}

Angular 7 development

Modify existing HtppClient Service

We modify the HttpClient service to add methods for performing add new employee and deleting employee in addition to getting the list of employees using the httpClient.

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

export class Employee{
  constructor(
    public empId:string,
    public name:string,
    public designation:string,
    public salary:string,
  ) {}
  
}

@Injectable({
  providedIn: 'root'
})
export class HttpClientService {

  constructor(
    private httpClient:HttpClient
  ) { 
     }

     getEmployees()
  {
    console.log("test call");
    return this.httpClient.get<Employee[]>('http://localhost:8080/employees');
  }

  public deleteEmployee(employee) {
    return this.httpClient.delete<Employee>("http://localhost:8080/employees" + "/"+ employee.empId);
  }

  public createEmployee(employee) {
    return this.httpClient.post<Employee>("http://localhost:8080/employees", employee);
  }
}

Adding BootStrap CSS

In the style.css add the bootstrap css url-

/* You can add global styles to this file, and also import other style files */
@import url(https://unpkg.com/[email protected]/dist/css/bootstrap.min.css)

Modify existing employee component to add delete functionality

In the employee.component.ts file add a call for deleting the employee in addition to getting the list of employees.

import { Component, OnInit } from '@angular/core';
import { HttpClientService, Employee } from '../service/http-client.service';

@Component({
  selector: 'app-employee',
  templateUrl: './employee.component.html',
  styleUrls: ['./employee.component.css']
})
export class EmployeeComponent implements OnInit {

  employees: Employee[];
   
  constructor(
    private httpClientService: HttpClientService
  ) { }

  ngOnInit() {
    this.httpClientService.getEmployees().subscribe(
     response =>{this.employees = response;}
    );
  }

  deleteEmployee(employee: Employee): void {
    this.httpClientService.deleteEmployee(employee)
      .subscribe( data => {
        this.employees = this.employees.filter(u => u !== employee);
      })
  };
}

We will be displaying the list of employees in employee.component.html and give users option to delete the employee.

<div class="col-md-6">
  <table class="table table-striped">
  <thead>
  <tr>
    <th>name</th>
    <th>designation</th>
    </tr>
  </thead>
  <tbody>
      <tr *ngFor="let employee of employees">
          <td>{{employee.name}}</td>
          <td>{{employee.designation}}</td>
          <td><button class="btn btn-danger" (click)="deleteEmployee(employee)"> Delete Employee</button></td>
          </tr>
  </tbody>
    </table>

  </div>

Now if we go to localhost:4200

Creating the add employee component

We will be creating a new component named add-employee

ng generate component add-employee

Modify the add-employee.component.ts to make call to spring boot for creating new employee using the httpClientService which is injected in the class using constructor injection.

import { Component, OnInit } from '@angular/core';
import { HttpClientService, Employee } from '../service/http-client.service';

@Component({
  selector: 'app-add-employee',
  templateUrl: './add-employee.component.html',
  styleUrls: ['./add-employee.component.css']
})
export class AddEmployeeComponent implements OnInit {

  user: Employee = new Employee("","","","");

  constructor(
    private httpClientService: HttpClientService
  ) { }

  ngOnInit() {
  }

  createEmployee(): void {
    this.httpClientService.createEmployee(this.user)
        .subscribe( data => {
          alert("Employee created successfully.");
        });

  };

}
	

Modify the add-employee.component.html to create form for getting the new employee details for the employee object to be created.

<div class="col-md-6">
<h2 class="text-center">Add Employee</h2>
<form>
  <div class="form-group">
    <label for="name">Name:</label>
    <input type="name" [(ngModel)]="user.name" placeholder="Name" name="name" class="form-control" id="name">
  </div>

  <div class="form-group">
    <label for="designation">Designation:</label>
    <input [(ngModel)]="user.designation" placeholder="Designation" name="designation" class="form-control" id="designation">
  </div>

  <div class="form-group">
    <label for="empId">Employee Id</label>
    <input [(ngModel)]="user.empId" placeholder="Employee Id" name="Employee Id" class="form-control" id="employeeid">
  </div>

  <button class="btn btn-success" (click)="createEmployee()">Create</button>
</form>
</div>

Since we are using ngModel directive, we will need to add the FormsModule in the app.module.ts- If this is not done you will get an exception as follows - Can’t bind to ‘ngModel’ since it isn’t a known property of ‘input’. ("

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { EmployeeComponent } from './employee/employee.component';
import { HttpClientModule } from '@angular/common/http';
import { AddEmployeeComponent } from './add-employee/add-employee.component';
import { FormsModule } from '@angular/forms';
import { HeaderComponent } from './header/header.component';
import { FooterComponent } from './footer/footer.component';

@NgModule({
  declarations: [
    AppComponent,
    EmployeeComponent,
    AddEmployeeComponent,
    HeaderComponent,
    FooterComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

In the app.routing.js add the route for this add employee component

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { EmployeeComponent } from './employee/employee.component';
import { AddEmployeeComponent } from './add-employee/add-employee.component';

const routes: Routes = [
  { path:'', component: EmployeeComponent},
  { path:'addemployee', component: AddEmployeeComponent},
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Go to localhost:8080/addemployee

Creating the header menu

Create new header component-

ng generate component header

Modify the header.component.html to create the menu with links to the view employees and add new employee pages.

  <header>
  <nav class ="navbar navbar-expand-md navbar-dark bg-dark">
  <div><a href="https://www.javainuse.com" class="navbar-brand">JavaInUse</a></div>
  
  <ul class="navbar-nav">
    <li><a  routerLink="/" class="nav-link">View Employees</a></li>
    <li><a  routerLink="/addemployee" class="nav-link">Add New Employee</a></li>
  
  </ul>
  
  </nav>
  
  </header>

Create Footer Component

Create a new component named footer-

ng generate component footer

In the footer specify the data-

<footer class="footer">
  <div class="container">
      <span class="text-muted">All Rights Reserved 2019 @JavaInUse</span>
  </div>

</footer>

Modify the footer.component.css-

    .footer {
    position: absolute;
    bottom: 0;
    width:100%;
    height: 40px;
    background-color: #222222;
}

  • Modify the app.component.html to add the footer and menu to the application byadding the selector tags.
<app-header></app-header>
<router-outlet></router-outlet> 
<app-footer></app-footer>

Go to localhost:4200

Download Source Code

Download it -

GITHUB- Angular 7 CRUD example code

Spring Boot CRUD example code

Popular Posts

Full Stack Web Development with Angular and Spring MVC

Building Web App using ASP.NET Web API Angular 7 and SQL Server

Angular 7 Tutorial - Learn Angular 7 by Example

Build a Basic App with Spring Boot and JPA using PostgreSQL

Build a Simple CRUD App with Spring Boot and Vue.js

Build a Basic CRUD App with Laravel and Angular

AngularJS tutorial for beginners with NodeJS, ExpressJS and MongoDB

MEAN Stack Tutorial MongoDB, ExpressJS, AngularJS and NodeJS

Build a CRUD App with Angular and Firebase

Angular Authentication Tutorial

Angular 7 (formerly Angular 2) - The Complete Guide

Angular & NodeJS - The MEAN Stack Guide

Learn and Understand AngularJS

Angular Crash Course for Busy Developers

The Complete Angular Course: Beginner to Advanced

Angular (Full App) with Angular Material, Angularfire & NgRx

The Web Developer Bootcamp

Securing RESTful API with Spring Boot, Security, and Data MongoDB

Securing RESTful API with Spring Boot, Security, and Data MongoDB

A comprehensive step by step tutorial on securing or authentication RESTful API with Spring Boot, Security, and Data MongoDB

A comprehensive step by step tutorial on securing or authentication RESTful API with Spring Boot, Security, and Data MongoDB. Previously, we have shown you how to securing Spring Boot, MVC and MongoDB web application. In this tutorial, the secure endpoint will restrict the access from an unauthorized request. Every request to secure endpoint should bring authorization token with it. Of course, there will be an endpoint for login which will get authorization token after successful login.

Table of Contents:

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

We assume that you already installed all required software, tools, and frameworks. So, we will not cover how to install that software, tools, and frameworks.

1. Generate a New Spring Boot Gradle Project

To create or generate a new Spring Boot Application or Project, simply go to Spring Initializer. Fill all required fields as below then click on Generate Project button.

The project will automatically be downloaded as a Zip file. Next, extract the zipped project to your java projects folder. On the project folder root, you will find build.gradle file for register dependencies, initially it looks like this.

buildscript {
&nbsp;&nbsp; &nbsp;ext {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;springBootVersion = '2.1.2.RELEASE'
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;repositories {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;mavenCentral()
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;dependencies {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
&nbsp;&nbsp; &nbsp;}
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group = 'com.djamware'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
&nbsp;&nbsp; &nbsp;mavenCentral()
}

dependencies {
&nbsp;&nbsp; &nbsp;implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
&nbsp;&nbsp; &nbsp;implementation 'org.springframework.boot:spring-boot-starter-security'
&nbsp;&nbsp; &nbsp;implementation 'org.springframework.boot:spring-boot-starter-web'
&nbsp;&nbsp; &nbsp;testImplementation 'org.springframework.boot:spring-boot-starter-test'
&nbsp;&nbsp; &nbsp;testImplementation 'org.springframework.security:spring-security-test'
}

Now, you can work with the source code of this Spring Boot Project using your own IDE or Text Editor. We are using Spring Tool Suite (STS). In STS, import the extracted zipped file as Existing Gradle Project.

Next, we have to add the JWT library to the build.gradle as the dependency. Open and edit build.gradle then add this line to dependencies after other implementation.

implementation 'io.jsonwebtoken:jjwt:0.9.1'

Next, compile the Gradle Project by type this command from Terminal or CMD.

./gradlew compile

Or you can compile directly from STS by right-clicking the project name then choose Gradle -> Refresh Gradle Project. Next, open and edit src/main/resources/application.properties then add these lines.

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

2. Create Product, User and Role Model or Entity Classes

We will be creating all required models or entities for products, user and role. In STS, right-click the project name -> New -> Class. Fill the package with com.djamware.SecurityRest.models, the name with Product, and leave other fields and checkbox as default then click Finish Button.

Next, open and edit src/main/java/com/djamware/SecurityRest/models/Product.java then add this annotation above the class name that will point to MongoDB collection.

@Document(collection = "products")

Inside Product class, add these variables.

@Id
String id;
String prodName;
String prodDesc;
Double prodPrice;
String prodImage;

Add constructors after the variable or fields.

public Product() {
}

public Product(String prodName, String prodDesc, Double prodPrice, String prodImage) {
&nbsp;&nbsp; &nbsp;super();
&nbsp;&nbsp; &nbsp;this.prodName = prodName;
&nbsp;&nbsp; &nbsp;this.prodDesc = prodDesc;
&nbsp;&nbsp; &nbsp;this.prodPrice = prodPrice;
&nbsp;&nbsp; &nbsp;this.prodImage = prodImage;
}

Generate or create Getter and Setter for each field.

public String getId() {
&nbsp;&nbsp; &nbsp;return id;
}

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

public String getProdName() {
&nbsp;&nbsp; &nbsp;return prodName;
}

public void setProdName(String prodName) {
&nbsp;&nbsp; &nbsp;this.prodName = prodName;
}

public String getProdDesc() {
&nbsp;&nbsp; &nbsp;return prodDesc;
}

public void setProdDesc(String prodDesc) {
&nbsp;&nbsp; &nbsp;this.prodDesc = prodDesc;
}

public Double getProdPrice() {
&nbsp;&nbsp; &nbsp;return prodPrice;
}

public void setProdPrice(Double prodPrice) {
&nbsp;&nbsp; &nbsp;this.prodPrice = prodPrice;
}

public String getProdImage() {
&nbsp;&nbsp; &nbsp;return prodImage;
}

public void setProdImage(String prodImage) {
&nbsp;&nbsp; &nbsp;this.prodImage = prodImage;
}

Using STS you can organize imports automatically from the menu Source -> Organize Imports then you can see the imports after the package name.

package com.djamware.SecurityRest.models;

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

You can do the same way as the above step for User and Role class. Here’s the User class looks like.

package com.djamware.SecurityRest.models;

import java.util.Set;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.IndexDirection;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;

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

&nbsp;&nbsp; &nbsp;@Id
&nbsp;&nbsp; &nbsp;private String id;
&nbsp;&nbsp; &nbsp;@Indexed(unique = true, direction = IndexDirection.DESCENDING, dropDups = true)
&nbsp;&nbsp; &nbsp;private String email;
&nbsp;&nbsp; &nbsp;private String password;
&nbsp;&nbsp; &nbsp;private String fullname;
&nbsp;&nbsp; &nbsp;private boolean enabled;
&nbsp;&nbsp; &nbsp;@DBRef
&nbsp;&nbsp; &nbsp;private Set<Role> roles;
&nbsp;&nbsp; &nbsp;public String getId() {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return id;
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;public void setId(String id) {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.id = id;
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;public String getEmail() {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return email;
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;public void setEmail(String email) {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.email = email;
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;public String getPassword() {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return password;
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;public void setPassword(String password) {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.password = password;
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;public String getFullname() {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return fullname;
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;public void setFullname(String fullname) {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.fullname = fullname;
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;public boolean isEnabled() {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return enabled;
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;public void setEnabled(boolean enabled) {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.enabled = enabled;
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;public Set<Role> getRoles() {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return roles;
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;public void setRoles(Set<Role> roles) {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.roles = roles;
&nbsp;&nbsp; &nbsp;}

}

And the Role class will be like this.

package com.djamware.SecurityRest.models;

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

@Document(collection = "roles")
public class Role {

&nbsp;&nbsp; &nbsp;@Id
&nbsp; &nbsp; private String id;
&nbsp; &nbsp; @Indexed(unique = true, direction = IndexDirection.DESCENDING, dropDups = true)

&nbsp; &nbsp; private String role;
&nbsp;&nbsp; &nbsp;public String getId() {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return id;
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;public void setId(String id) {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.id = id;
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;public String getRole() {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return role;
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;public void setRole(String role) {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.role = role;
&nbsp;&nbsp; &nbsp;}

}

3. Create Product, User and Role Repository Interfaces

Next steps to create Product, User, and Role Repository Interfaces. From the STS, right-click the project name -> New -> Interface then fill all required fields and checkboxes as below before click Finish button.

Next, open and edit src/main/java/com/djamware/SecurityRest/repositories/ProductRepository.java then add extends to MongoDB CRUD Repository.

public interface ProductRepository extends CrudRepository<Product, String> {

}

Inside the class name add this method.

@Override
void delete(Product deleted);

Organize all required imports.

import org.springframework.data.repository.CrudRepository;
import com.djamware.SecurityRest.models.Product;

The same way can be applied to User and Role repositories. So, the User Repository Interface will look like this.

package com.djamware.SecurityRest.repositories;

import org.springframework.data.mongodb.repository.MongoRepository;
import com.djamware.SecurityRest.models.User;

public interface UserRepository extends MongoRepository<User, String> {

&nbsp;&nbsp; &nbsp;User findByEmail(String email);
}

And the Role Repository Interface will look like this.

package com.djamware.SecurityRest.repositories;

import org.springframework.data.mongodb.repository.MongoRepository;
import com.djamware.SecurityRest.models.Role;

public interface RoleRepository extends MongoRepository<Role, String> {

&nbsp;&nbsp; &nbsp;Role findByRole(String role);
}

4. Create a Custom User Details Service

To implements authentication using existing User and Role from MongoDB, we have to create a custom user details service. From the STS, right-click the project name -> New -> Class File then fill all required fields and checkboxes as below before clicking the finish button.

Next, open and edit src/main/java/com/djamware/SecurityRest/services/CustomUserDetailsService.java then give an annotation above the class name and implement the Spring Security User Details Service.

@Service
public class CustomUserDetailsService implements UserDetailsService {
}

Next, inject all required beans at the first line of the class bracket.

@Autowired
private UserRepository userRepository;

@Autowired
private RoleRepository roleRepository;

@Autowired
private PasswordEncoder bCryptPasswordEncoder;

Add a method to find a user by email field.

public User findUserByEmail(String email) {
&nbsp; &nbsp; return userRepository.findByEmail(email);
}

Add a method to save a new user.

public void saveUser(User user) {
&nbsp; &nbsp; user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
&nbsp; &nbsp; user.setEnabled(true);
&nbsp; &nbsp; Role userRole = roleRepository.findByRole("ADMIN");
&nbsp; &nbsp; user.setRoles(new HashSet<>(Arrays.asList(userRole)));
&nbsp; &nbsp; userRepository.save(user);
}

Override the Spring Security User Details to load User by email.

@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {

&nbsp; &nbsp; User user = userRepository.findByEmail(email);
&nbsp; &nbsp; if(user != null) {
&nbsp; &nbsp; &nbsp; &nbsp; List<GrantedAuthority> authorities = getUserAuthority(user.getRoles());
&nbsp; &nbsp; &nbsp; &nbsp; return buildUserForAuthentication(user, authorities);
&nbsp; &nbsp; } else {
&nbsp; &nbsp; &nbsp; &nbsp; throw new UsernameNotFoundException("username not found");
&nbsp; &nbsp; }
}

Add a method to get a set of Roles that related to a user.

private List<GrantedAuthority> getUserAuthority(Set<Role> userRoles) {
&nbsp; &nbsp; Set<GrantedAuthority> roles = new HashSet<>();
&nbsp; &nbsp; userRoles.forEach((role) -> {
&nbsp; &nbsp; &nbsp; &nbsp; roles.add(new SimpleGrantedAuthority(role.getRole()));
&nbsp; &nbsp; });

&nbsp; &nbsp; List<GrantedAuthority> grantedAuthorities = new ArrayList<>(roles);
&nbsp; &nbsp; return grantedAuthorities;
}

Add a method for authentication purpose.

private UserDetails buildUserForAuthentication(User user, List<GrantedAuthority> authorities) {
&nbsp; &nbsp; return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), authorities);
}

5. Configure Spring Boot Security Rest

Now, the main purpose of this tutorial is configuring Spring Security Rest. First, we have to create a bean for JWT token generation and validation. Right-click the project name -> New -> Class File. Fill the package name as com.djamware.SecurityRest.configs and the Class name as JwtTokenProvider then click the Finish button. Next, open and edit that newly created class file then give it an annotation above the class name.

@Component
public class JwtTokenProvider {
}

Add variables and injected bean inside the class bracket at the top lines.

@Value("${security.jwt.token.secret-key:secret}")
private String secretKey = "secret";

@Value("${security.jwt.token.expire-length:3600000}")
private long validityInMilliseconds = 3600000; // 1h

@Autowired
private CustomUserDetailsService userDetailsService;

Add a method for initialization.

@PostConstruct
protected void init() {
&nbsp; &nbsp; secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes());
}

Add a method to create a JWT token.

public String createToken(String username, Set<Role> set) {
&nbsp; &nbsp; Claims claims = Jwts.claims().setSubject(username);
&nbsp; &nbsp; claims.put("roles", set);
&nbsp; &nbsp; Date now = new Date();
&nbsp; &nbsp; Date validity = new Date(now.getTime() + validityInMilliseconds);
&nbsp; &nbsp; return Jwts.builder()//
&nbsp; &nbsp; &nbsp; &nbsp; .setClaims(claims)//
&nbsp; &nbsp; &nbsp; &nbsp; .setIssuedAt(now)//
&nbsp; &nbsp; &nbsp; &nbsp; .setExpiration(validity)//
&nbsp; &nbsp; &nbsp; &nbsp; .signWith(SignatureAlgorithm.HS256, secretKey)//
&nbsp; &nbsp; &nbsp; &nbsp; .compact();
}

Add a method to load User by username.

public Authentication getAuthentication(String token) {
&nbsp; &nbsp; UserDetails userDetails = this.userDetailsService.loadUserByUsername(getUsername(token));
&nbsp; &nbsp; return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
}

Add a method to get the username by JWT token.

public String getUsername(String token) {
&nbsp; &nbsp; return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject();
}

Add a method to resolve JWT token from request headers of Authorization that has a Bearer prefix.

public String resolveToken(HttpServletRequest req) {
&nbsp; &nbsp; String bearerToken = req.getHeader("Authorization");
&nbsp; &nbsp; if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
&nbsp; &nbsp; &nbsp; &nbsp; return bearerToken.substring(7, bearerToken.length());
&nbsp; &nbsp; }
&nbsp; &nbsp; return null;
}

Add a method to validate a JWT token.

public boolean validateToken(String token) {
&nbsp; &nbsp; try {
&nbsp; &nbsp; &nbsp; &nbsp; Jws<Claims> claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);
&nbsp; &nbsp; &nbsp; &nbsp; if (claims.getBody().getExpiration().before(new Date())) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; return true;
&nbsp; &nbsp; } catch (JwtException | IllegalArgumentException e) {
&nbsp; &nbsp; &nbsp; &nbsp; throw new JwtException("Expired or invalid JWT token");
&nbsp; &nbsp; }
}

Finally, organize imports like below.

package com.djamware.SecurityRest.configs;

import java.util.Base64;
import java.util.Date;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import com.djamware.SecurityRest.models.Role;
import com.djamware.SecurityRest.services.CustomUserDetailsService;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

Next, create a JWT filter class with the name JwtTokenFilter in configs package that extends Spring GenericFilterBean. Replace all Java codes with these lines of codes.

package com.djamware.SecurityRest.configs;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.GenericFilterBean;

public class JwtTokenFilter extends GenericFilterBean {

&nbsp;&nbsp; &nbsp;private JwtTokenProvider jwtTokenProvider;

&nbsp; &nbsp; public JwtTokenFilter(JwtTokenProvider jwtTokenProvider) {
&nbsp; &nbsp; &nbsp; &nbsp; this.jwtTokenProvider = jwtTokenProvider;
&nbsp; &nbsp; }

&nbsp; &nbsp; @Override
&nbsp; &nbsp; public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain)
&nbsp; &nbsp; &nbsp; &nbsp; throws IOException, ServletException {
&nbsp; &nbsp; &nbsp; &nbsp; String token = jwtTokenProvider.resolveToken((HttpServletRequest) req);
&nbsp; &nbsp; &nbsp; &nbsp; if (token != null && jwtTokenProvider.validateToken(token)) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Authentication auth = token != null ? jwtTokenProvider.getAuthentication(token) : null;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SecurityContextHolder.getContext().setAuthentication(auth);
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; filterChain.doFilter(req, res);
&nbsp; &nbsp; }
}

Next, create a class with the name JwtConfigurer for JWT configuration in configs package then replace all codes with these lines of codes.

package com.djamware.SecurityRest.configs;

import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

public class JwtConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {

&nbsp;&nbsp; &nbsp;private JwtTokenProvider jwtTokenProvider;

&nbsp; &nbsp; public JwtConfigurer(JwtTokenProvider jwtTokenProvider) {
&nbsp; &nbsp; &nbsp; &nbsp; this.jwtTokenProvider = jwtTokenProvider;
&nbsp; &nbsp; }

&nbsp; &nbsp; @Override
&nbsp; &nbsp; public void configure(HttpSecurity http) throws Exception {
&nbsp; &nbsp; &nbsp; &nbsp; JwtTokenFilter customFilter = new JwtTokenFilter(jwtTokenProvider);
&nbsp; &nbsp; &nbsp; &nbsp; http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
&nbsp; &nbsp; }
}

Finally, we have to configure the Spring Security by creating a Java class file inside configs package with the name WebSecurityConfig. Give annotations to this class and extends Spring WebSecurityConfigurerAdapter.

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
}

Inject JWT token provider inside this class.

@Autowired
JwtTokenProvider jwtTokenProvider;

Add an override method to configure Authentication Manager Builder.

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
&nbsp;&nbsp; &nbsp;UserDetailsService userDetailsService = mongoUserDetails();
&nbsp;&nbsp; &nbsp;auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());

}

Next, add an override method to configure Spring Security Http Security.

@Override
protected void configure(HttpSecurity http) throws Exception {
&nbsp;&nbsp; &nbsp;http.httpBasic().disable().csrf().disable().sessionManagement()
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;.antMatchers("/api/auth/login").permitAll().antMatchers("/api/auth/register").permitAll()
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;.antMatchers("/api/products/**").hasAuthority("ADMIN").anyRequest().authenticated().and().csrf()
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;.disable().exceptionHandling().authenticationEntryPoint(unauthorizedEntryPoint()).and()
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;.apply(new JwtConfigurer(jwtTokenProvider));
}

Next, declare all required beans for this configuration.

@Bean
public PasswordEncoder bCryptPasswordEncoder() {
&nbsp;&nbsp; &nbsp;return new BCryptPasswordEncoder();
}

@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
&nbsp;&nbsp; &nbsp;return super.authenticationManagerBean();
}

@Bean
public AuthenticationEntryPoint unauthorizedEntryPoint() {
&nbsp;&nbsp; &nbsp;return (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"Unauthorized");
}

@Bean
public UserDetailsService mongoUserDetails() {
&nbsp;&nbsp; &nbsp;return new CustomUserDetailsService();
}

6. Create Product and Authentication Controllers

Now it’s time for REST API endpoint. All RESTful API will be created from each controller. Product controller will handle CRUD endpoint of product and Authentication controller will handle login and register endpoint. Right-click project name -> New -> Class then fill the package with com.djamware.SecurityRest.controllers and the class name as ProductController. Open and edit the newly created class file then replace all codes with these lines of codes.

package com.djamware.SecurityRest.controllers;

import java.util.Optional;

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 com.djamware.SecurityRest.models.Product;
import com.djamware.SecurityRest.repositories.ProductRepository;

@RestController
public class ProductController {

&nbsp;&nbsp; &nbsp;@Autowired
&nbsp; &nbsp; ProductRepository productRepository;

&nbsp; &nbsp; @RequestMapping(method=RequestMethod.GET, value="/api/products")
&nbsp; &nbsp; public Iterable<Product> product() {
&nbsp; &nbsp; &nbsp; &nbsp; return productRepository.findAll();
&nbsp; &nbsp; }

&nbsp; &nbsp; @RequestMapping(method=RequestMethod.POST, value="/api/products")
&nbsp; &nbsp; public String save(@RequestBody Product product) {
&nbsp; &nbsp; &nbsp; &nbsp; productRepository.save(product);

&nbsp; &nbsp; &nbsp; &nbsp; return product.getId();
&nbsp; &nbsp; }

&nbsp; &nbsp; @RequestMapping(method=RequestMethod.GET, value="/api/products/{id}")
&nbsp; &nbsp; public Optional<Product> show(@PathVariable String id) {
&nbsp; &nbsp; &nbsp; &nbsp; return productRepository.findById(id);
&nbsp; &nbsp; }

&nbsp; &nbsp; @RequestMapping(method=RequestMethod.PUT, value="/api/products/{id}")
&nbsp; &nbsp; public Product update(@PathVariable String id, @RequestBody Product product) {
&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;Optional<Product> prod = productRepository.findById(id);
&nbsp; &nbsp; &nbsp; &nbsp; if(product.getProdName() != null)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prod.get().setProdName(product.getProdName());
&nbsp; &nbsp; &nbsp; &nbsp; if(product.getProdDesc() != null)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prod.get().setProdDesc(product.getProdDesc());
&nbsp; &nbsp; &nbsp; &nbsp; if(product.getProdPrice() != null)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prod.get().setProdPrice(product.getProdPrice());
&nbsp; &nbsp; &nbsp; &nbsp; if(product.getProdImage() != null)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prod.get().setProdImage(product.getProdImage());
&nbsp; &nbsp; &nbsp; &nbsp; productRepository.save(prod.get());
&nbsp; &nbsp; &nbsp; &nbsp; return prod.get();
&nbsp; &nbsp; }

&nbsp; &nbsp; @RequestMapping(method=RequestMethod.DELETE, value="/api/products/{id}")
&nbsp; &nbsp; public String delete(@PathVariable String id) {
&nbsp; &nbsp; &nbsp; &nbsp; Optional<Product> product = productRepository.findById(id);
&nbsp; &nbsp; &nbsp; &nbsp; productRepository.delete(product.get());

&nbsp; &nbsp; &nbsp; &nbsp; return "product deleted";
&nbsp; &nbsp; }
}

For login, we need to create a POJO to mapping required fields of User. Create a new class file with the name AuthBody inside controllers package then replace all Java codes with these lines of codes.

package com.djamware.SecurityRest.controllers;

public class AuthBody {

&nbsp;&nbsp; &nbsp;private String email;
&nbsp; &nbsp; private String password;

&nbsp;&nbsp; &nbsp;public String getEmail() {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return email;
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;public void setEmail(String email) {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.email = email;
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;public String getPassword() {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return password;
&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;public void setPassword(String password) {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.password = password;
&nbsp;&nbsp; &nbsp;}

}

Finally, create a controller for authentication with the name AuthController inside the controllers’ package. Open and edit that newly created file then replace all Java codes with these lines of codes.

package com.djamware.SecurityRest.controllers;

import static org.springframework.http.ResponseEntity.ok;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.djamware.SecurityRest.configs.JwtTokenProvider;
import com.djamware.SecurityRest.models.User;
import com.djamware.SecurityRest.repositories.UserRepository;
import com.djamware.SecurityRest.services.CustomUserDetailsService;

@RestController
@RequestMapping("/api/auth")
public class AuthController {

&nbsp;&nbsp; &nbsp;@Autowired
&nbsp;&nbsp; &nbsp;AuthenticationManager authenticationManager;

&nbsp;&nbsp; &nbsp;@Autowired
&nbsp;&nbsp; &nbsp;JwtTokenProvider jwtTokenProvider;

&nbsp;&nbsp; &nbsp;@Autowired
&nbsp;&nbsp; &nbsp;UserRepository users;

&nbsp;&nbsp; &nbsp;@Autowired
&nbsp;&nbsp; &nbsp;private CustomUserDetailsService userService;

&nbsp;&nbsp; &nbsp;@SuppressWarnings("rawtypes")
&nbsp;&nbsp; &nbsp;@PostMapping("/login")
&nbsp;&nbsp; &nbsp;public ResponseEntity login(@RequestBody AuthBody data) {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;try {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;String username = data.getEmail();
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, data.getPassword()));
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;String token = jwtTokenProvider.createToken(username, this.users.findByEmail(username).getRoles());
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;Map<Object, Object> model = new HashMap<>();
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;model.put("username", username);
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;model.put("token", token);
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return ok(model);
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} catch (AuthenticationException e) {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;throw new BadCredentialsException("Invalid email/password supplied");
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;}

&nbsp;&nbsp; &nbsp;@SuppressWarnings("rawtypes")
&nbsp;&nbsp; &nbsp;@PostMapping("/register")
&nbsp;&nbsp; &nbsp;public ResponseEntity register(@RequestBody User user) {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;User userExists = userService.findUserByEmail(user.getEmail());
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (userExists != null) {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;throw new BadCredentialsException("User with username: " + user.getEmail() + " already exists");
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;userService.saveUser(user);
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;Map<Object, Object> model = new HashMap<>();
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;model.put("message", "User registered successfully");
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return ok(model);
&nbsp;&nbsp; &nbsp;}
}

7. Run and Test Spring Boot Security Rest using Postman

Before run and test the application, we have to populate a Role data first. Open and edit src/main/java/com/djamware/SecurityRest/SecurityRestApplication.java then add these lines of codes inside the initialization method.

@Bean
CommandLineRunner init(RoleRepository roleRepository) {

&nbsp; &nbsp; return args -> {

&nbsp; &nbsp; &nbsp; &nbsp; Role adminRole = roleRepository.findByRole("ADMIN");
&nbsp; &nbsp; &nbsp; &nbsp; if (adminRole == null) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Role newAdminRole = new Role();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newAdminRole.setRole("ADMIN");
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; roleRepository.save(newAdminRole);
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; };

}

Next, make sure you have run the MongoDB server on your local machine then run the Gradle application using this command.

./gradlew bootRun

Or in STS just right-click the project name -> Run As -> Spring Boot App. Next, open the Postman application then change the method to GET and address to localhost:8080/api/products then click Send button.

You will see this response in the bottom panel of Postman.

{
&nbsp; &nbsp; "timestamp": "2019-03-07T13:16:34.935+0000",
&nbsp; &nbsp; "status": 401,
&nbsp; &nbsp; "error": "Unauthorized",
&nbsp; &nbsp; "message": "Unauthorized",
&nbsp; &nbsp; "path": "/api/products"
}

Next, change the method to POST then address to localhost:8080/api/auth/register then fill the body with raw data as below image then click Send button.

You will get the response in the bottom panel of Postman.

{
&nbsp; &nbsp; "message": "User registered successfully"
}

Next, change the address to localhost:8080/api/auth/login and change the body as below then click Send button.

{ "email":"[email&nbsp;protected]", "password": "q1w2we3r4" }

You will see this response in the bottom panel of Postman.

{
&nbsp; &nbsp; "username": "[email&nbsp;protected]",
&nbsp; &nbsp; "token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJpbmZvQGRqYW13YXJlLmNvbSIsInJvbGVzIjpbeyJpZCI6IjVjODBjNjIzYjIwMTkxNGIyYTY5N2U4ZCIsInJvbGUiOiJBRE1JTiJ9XSwiaWF0IjoxNTUxOTY0OTc3LCJleHAiOjE1NTE5Njg1Nzd9.j5CHZ_LCmeQtdxQeH9eluxVXcOsHPWV1p8WnBn0CULo"
}

Copy the token then back to the GET product. Add a header with the name Authorization and the value that paste from a token that gets by login with additional Bearer prefix (with space) as below.

Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJpbmZvQGRqYW13YXJlLmNvbSIsInJvbGVzIjpbeyJpZCI6IjVjODBjNjIzYjIwMTkxNGIyYTY5N2U4ZCIsInJvbGUiOiJBRE1JTiJ9XSwiaWF0IjoxNTUxOTY0OTc3LCJleHAiOjE1NTE5Njg1Nzd9.j5CHZ_LCmeQtdxQeH9eluxVXcOsHPWV1p8WnBn0CULo

You should see this response after clicking the Send button.

[
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; "id": "5c80dc6cb20191520567b68a",
&nbsp; &nbsp; &nbsp; &nbsp; "prodName": "Dummy Product 1",
&nbsp; &nbsp; &nbsp; &nbsp; "prodDesc": "The Fresh Dummy Product in The world part 1",
&nbsp; &nbsp; &nbsp; &nbsp; "prodPrice": 100,
&nbsp; &nbsp; &nbsp; &nbsp; "prodImage": "https://dummyimage.com/600x400/000/fff"
&nbsp; &nbsp; }
]

You can test the POST product with the token in headers using the same way.

That it’s, the Securing RESTful API with Spring Boot, Security, and Data MongoDB tutorial. You can get the full source code from our GitHub.

Learn More

Build a Simple CRUD App with Spring Boot and Vue.js

Creating RESTful APIs with NodeJS and MongoDB Tutorial

MongoDB with Python Crash Course - Tutorial for Beginners

How to build RESTful APIs with ASP.NET Core

Understanding the basics of RESTful APIs

Developing RESTful APIs with Lumen (A PHP Micro-framework)

Java Programming Masterclass for Software Developers

Java In-Depth: Become a Complete Java Engineer!

JSP, Servlets and JDBC for Beginners: Build a Database App

JSP, Servlet, JSLT + Hibernate: A complete guide

Building a Web Application Using Spring Boot, Angular, and Maven

Building a Web Application Using Spring Boot, Angular, and Maven

In this article, we will explore the steps used to build a web application using Spring Boot with Angular and Maven and then launch it on a Tomcat Server.

In this article, we will explore the steps used to build a web application using Spring Boot with Angular and Maven and then launch it on a Tomcat Server.

Angular and Spring Boot are both great frameworks which are nowadays in great combination especially by java developers gladly used for building microservices.

In this article I want to show therefore how you can setup a parent maven project which includes an angular and spring boot child, which is finally be deployed on a tomcat server, including production ready jar with some pre-requisties.

Pre-Requisites

Since we are building the project locally and deploy, it’s recommended to try the below mentioned versions and then upgrade or downgrade as per your requirements.

Most importantly, you should also ahve some knowlegde of Spring, Angular, and Maven.

  • Maven version 3.5.2
  • Node version v8.9.3
  • Npm version v5.5.1
  • IntelliJ or any other IDE of your favourite
What Are We Going to Do?

Let’s start building the Spring Boot Project with the following structure.

I have named it AppName — you can specify the any application name youe like.

To begin, it’s recommneded to use https://start.spring.io because its simple and ease to use.

Also, you will need minimum dependencies shown above under the ‘Selected dependencies’ header.

Create Modules for Angular and a Service Module

Once you have downloaded a project and imported it into your favorite IDE, (mine is IntelliJ), right-click on the parent module, i.e AppName, and click ‘New Module’ as shown below.

It’s recommended that you create a module with the project name suffixed with the module name. For example, AppName-UI or AppName-Service.

Once the modules are created, you can see that each module will havea pom.xml file associated with it, as shown in the figure below.

Now its time to discuess what are the modules used for and their purpose.

AppName-Service

This module is used for generating the final depolyment jar which, in turn, has core logic, REST controllers, models, repository classes, etc.

It would also have all the HTML, CSS, and JS files needed for the application.

AppName-UI

This module will contain the Angular project along with the pom.xml

Let’s now examine the pom.xml file used in the project.

The struture of parent pom.xml in the AppName folder of the pom.xml in AppName-Service module are as follows:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>AppName</artifactId>
        <groupId>com.appname.tutorial</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>

    <artifactId>AppName-Service</artifactId>

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

</project>

Note: You have to remove the build configuration from the Parent pom.xml and place it the AppName-Service’s pom.xml.

Also, it’s important to add packaging in the AppName-Service’s pom.xml.

<packaging>Jar</packaging>

Let’s now look at building the Angular project.

You have to delete the src folder created in the AppName-UI module/folder.

Copy the pom.xml from the AppName-UI module and place it in your Desktop.

Navigate to AppName from the terminal and run the following commands:

cd ~/AppName
rm -rf AppName-UI

Create an Angular 6 Project Using Angular-CLI

Know more about https://cli.angular.io/.

Generate an Angular 6 project using the Angular-CLI from the AppName directory/folder. Navigate to the AppName directoryin the terminal and run the following command:

ng new AppName-UI

Once the above command has been run, you will see that Angular CLI generates a folder/directory including node_modules, package.json, angular-cli.json, etc.

Just to ensure the newly created Angular app runs fine, you can navigate to that folder and run the below command

ng serve

Note:Replace the pom.xml file from the Desktop which we copied in the previous step.

The structure of pom.xml file in the AppName-UI is as follows.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>AppName</artifactId>
        <groupId>com.appname.tutorial</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>

    <artifactId>AppName-UI</artifactId>

    <build>
        <plugins>
            <plugin>
                <groupId>com.github.eirslett</groupId>
                <artifactId>frontend-maven-plugin</artifactId>
                <version>0.0.28</version>
                <configuration>
                    <workingDirectory>./</workingDirectory>
                    <nodeVersion>${node.version}</nodeVersion>
                    <npmVersion>${npm.version}</npmVersion>
                    <nodeDownloadRoot>http://nodejs.org/dist/</nodeDownloadRoot>
                    <npmDownloadRoot>http://registry.npmjs.org/npm/-/</npmDownloadRoot>
                    <installDirectory>./</installDirectory>
                </configuration>
                <executions>
                    <execution>
                        <id>install node and npm</id>
                        <goals>
                            <goal>install-node-and-npm</goal>
                        </goals>
                        <phase>generate-resources</phase>
                    </execution>
                    <execution>
                        <id>npm install</id>
                        <goals>
                            <goal>npm</goal>
                        </goals>
                        <phase>generate-resources</phase>
                        <configuration>
                            <arguments>ci --loglevel=error</arguments>
                        </configuration>
                    </execution>
                    <execution>
                        <id>npm run-script build-prod</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>npm</goal>
                        </goals>
                        <configuration>
                            <arguments>run-script build-dev</arguments>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>

    </build>
</project>


Where Are We Now?

We have created a Spring Boot application running on port 8080. We’ve also created an Angular application running on port 4200.

But we still haven’t achieve our goal of running an Angular application on Spring Boot’s Tomcat Server.

Running an Angular Application on Spring Boot’s Tomcat Server

As you already know, when use ng serve or ng build, Angular CLI generates all the HTML, CSS, andJS files in the dist folder.

Now we need to move that dist folder to AppName-Service’s resources directory.

The easiest way to do that is to open the angular-cli.json file of our Angular application and modify the outDir property as shown below

So, basically, what we are saying is to put all the generated files into the resources of service folder.

Run the Application

Now it’s all yours.

Run mvn clean installfrom the project root directory. This will generate a jar file in the AppName-Service/target directory. It can be deployed to the Tomcat Server and the application can be viewed.

To run the Spring Boot application using Maven, run the following command from the AppName-Servicedirectory.

mvn spring-boot:run

Once the application has started, we should be able to see the index.html in the logs, and open the browser navigate to http://localhost:8080/index.html to see the welcome page.

Angular HTML page accessed via a Tomcat Server.

Complete source code is available on GitHub: https://github.com/ihappyk/AppName

Thanks for reading ❤

If you liked this post, share it with all of your programming buddies!

How to do internationalization (i18n) in Java 11, Spring Boot, and JavaScript

How to do internationalization (i18n) in Java 11, Spring Boot, and JavaScript

This tutorial will show you how to internationalize a simple Java app, a Spring Boot app with Thymeleaf, and a JavaScript Widget.

What are i18n and l10n? Internationalization (i18n) is the process of making your application capable of rendering its text in multiple languages. Localization (l10n) means your application has been coded in such a way that it meets language, cultural, or other requirements of a particular locale. These requirements can include formats for date, time, and currency, as well as symbols, icons, and colors, among many other things. i18n enables l10n.

Why is i18n and l10n important? Because you want to make your app accessible to as many users as possible! If you’re a native English speaker, you’re spoiled because English is currently the language of business, and many apps offer an English translation. Internationalizing your Java app is relatively straightforward, thanks to built-in mechanisms. Same goes for Spring Boot - it’s there by default!

This tutorial will show you how to internationalize a simple Java app, a Spring Boot app with Thymeleaf, and a JavaScript Widget.


Java i18n with Resource Bundles

A resource bundle is a .properties file that contains keys and values for specific languages. Using resource bundles allows you to make your code locale-independent. To see how this works, create a new directory on your hard drive for this tutorial’s exercises. For example, java-i18n-example. Navigate to this directory from the command line and create a Hello.java file.

public class Hello {
public static void main(String[] args) {
    System.out.println("Hello, World!");
}
}

Run java Hello.java and you should see “Hello, World!” printed to your console.

If you see any error similar to the one below, it’s because you’re using a Java version < 11. JEP 330 is an enhancement in Java 11 that allows you to run a single file of Java source code, without compiling it.

$ java Hello.java
Error: Could not find or load main class Hello.java

You can install Java 11 from AdoptOpenJDK 11 or use SDKMAN!

curl -s "https://get.sdkman.io" | bash

Once you have SDKMAN installed, you can list the available java versions with sdk list java:

$ sdk list java
Available Java Versions
 13.ea.07-open       8.0.202-zulu
 12.ea.31-open       8.0.202-amzn
  • 11.ea.26-open 8.0.202.j9-adpt
    11.0.2-sapmchn 8.0.202.hs-adpt
    11.0.2-zulu 8.0.202-zulufx
  • 11.0.2-open 8.0.201-oracle
    11.0.2.j9-adpt > + 8.0.181-zulu
    11.0.2.hs-adpt 7.0.181-zulu
    11.0.2-zulufx 1.0.0-rc-12-grl
  • 11.0.1-open 1.0.0-rc-11-grl
  • 11.0.0-open 1.0.0-rc-10-grl
    10.0.2-zulu 1.0.0-rc-9-grl
    10.0.2-open 1.0.0-rc-8-grl
    9.0.7-zulu
    9.0.4-open

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

    • local version
    • installed
      > - currently in use
      ================================================================================

Set up your environment to use the latest version of OpenJDK with the command below:

sdk default java 11.0.2-open

Now you should be able to run your Hello.java as a Java program.

$ java Hello.java
Hello, World!

Look Ma! No compiling needed!! 😃

Create a messages_en_US.properties file in the same directory and add keys + translations for the terms hello and world.

hello=Hello
world=World

Create messages_es.properties and populate it with Spanish translations.

hello=Hola
world=Mundo

Modify Hello.java to use Locale and ResourceBundle to retrieve the translations from these files.

import java.util.Locale;
import java.util.ResourceBundle;

public class Hello {

public static void main(String[] args) {
    String language = "en";
    String country = "US";

    if (args.length == 2) {
        language = args[0];
        country = args[1];
    }

    var locale = new Locale(language, country);
    var messages = ResourceBundle.getBundle("messages", locale);

    System.out.print(messages.getString("hello") + " ");
    System.out.println(messages.getString("world"));
}

}

Run your Java program again, and you should see “Hello World”.

$ java Hello.java
Hello World

Improve the parsing of arguments to allow only specifying the language.

if (args.length == 1) {
language = args[0];
} else if (args.length == 2) {
language = args[0];
country = args[1];
}

Run the same command with an es argument and you’ll see a Spanish translation:

$ java Hello.java es
Hola Mundo

Yeehaw! It’s pretty cool that Java has i18n built-in, eh?

Internationalization with Spring Boot and Thymeleaf

Spring Boot has i18n built-in thanks to the Spring Framework and its MessageSource implementations. There’s a ResourceBundleMessageSource that builds on ResourceBundle, as well as a ReloadableResourceBundleMessageSource that should be self-explanatory.

Inject MessageSource into a Spring bean and call getMessage(key, args, locale) to your heart’s content! Using MessageSource will help you on the server, but what about in your UI? Let’s create a quick app to show you how you can add internationalization with Thymeleaf.

Go to start.spring.io and select Web and Thymeleaf as dependencies. Click Generate Project and download the resulting demo.zip file. If you’d rather do it from the command line, you can use HTTPie to do the same thing.

mkdir bootiful-i18n
cd bootiful-i18n
http https://start.spring.io/starter.zip dependencies==web,thymeleaf -d | tar xvz

Open the project in your favorite IDE and create HomeController.java in src/main/java/com/example/demo.

package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HomeController {

@GetMapping("/")
String home() {
    return "home";
}

}

Create a Thymeleaf template at src/main/resources/templates/home.html that will render the “home” view.

<html xmlns:th="http://www.thymeleaf.org">
<body>
<h1 th:text="#{title}"></h1>
<p th:text="#{message}"></p>
</body>
</html>

Add a messages.properties file in src/main/resources that defines your default language (English in this case).

title=Welcome
message=Hello! I hope you're having a great day.

Add a Spanish translation in the same directory, in a messages_es.properties file.

title=Bienvenida
message=¡Hola! Espero que estas teniendo un gran día. 😃

Spring Boot uses Spring’s LocaleResolver and (by default) its AcceptHeaderLocalResolver implementation. If your browser sends an accept-language header, Spring Boot will try to find messages that match.

To test it out, open Chrome and enter chrome://settings/languages in the address bar. Expand the top “Language” box, click Add languages and search for “Spanish”. Add the option without a country and move it to the top language in your preferences. It should look like the screenshot below when you’re finished.

For Firefox, navigate to about:preferences, scroll down to “Language and Appearance” and click the Choose button next to “Choose your preferred language for displaying pages”. Select Spanish and move it to the top.

Once you have your browser set to return Spanish, start your Spring Boot app with ./mvnw spring-boot:run (or mvnw spring-boot:run if you’re using Windows).

| | Add <defaultGoal>spring-boot:run</defaultGoal> in the <build> section of your pom.xml if you want to only type ./mvnw to start your app. |

Navigate to http://localhost:8080 and you should see a page with Spanish words.


Add the Ability to Change Locales with a URL Parameter

This is a nice setup, but you might want to allow users to set their own language. You might’ve seen this on websites in the wild, where they have a flag that you can click to change to that country’s language. To make this possible in Spring Boot, create a MvcConfigurer class alongside your HomeController.

package com.example.demo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;

@Configuration
public class MvcConfigurer implements WebMvcConfigurer {

@Bean
public LocaleResolver localeResolver() {
    return new CookieLocaleResolver();
}

@Bean
public LocaleChangeInterceptor localeInterceptor() {
    LocaleChangeInterceptor localeInterceptor = new LocaleChangeInterceptor();
    localeInterceptor.setParamName("lang");
    return localeInterceptor;
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(localeInterceptor());
}

}

This class uses a CookieLocaleResolver that’s useful for saving the locale preference in a cookie, and defaulting to the accept-language header if none exists.

Restart your server and you should be able to override your browser’s language preference by navigating to http://localhost:8080/?lang=en.

Your language preference will be saved in a cookie, so if you navigate back to http://localhost:8080, the page will render in English. If you quit your browser and restart, you’ll be back to using your browser’s language preference.

Hot Reloading Thymeleaf Templates and Resource Bundles in Spring Boot 2.1

If you’d like to modify your Thymeleaf templates and see those changes immediately when you refresh your browser, you can add Spring Boot’s Developer Tools to your pom.xml.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>

This is all you need to do if you have your IDE setup to copy resources when you save a file. If you’re not using an IDE, you’ll need to define a property in your application.properties:

spring.thymeleaf.prefix=file:src/main/resources/templates/

To hot-reload changes to your i18n bundles, you’ll need to rebuild your project (for example, by running ./mvnw compile). If you’re using Eclipse, a rebuild and restart should happen automatically for you. If you’re using IntelliJ IDEA, you’ll need to go to your run configuration and change “On frame deactivation” to be Update resources.

See this Stack Overflow answer for more information.

Customize the Language used by Okta’s Sign-In Widget

The last example I’d like to show you is a Spring Boot app with Okta’s embedded Sign-In Widget. The Sign-In Widget is smart enough to render the language based on your browser’s accept-language header.

However, if you want to sync it up with your Spring app’s LocalResolver, you need to do a bit more configuration. Furthermore, you can customize things so it sets the locale from the user’s locale setting in Okta.

To begin, export the custom login example for Spring Boot:

svn export https://github.com/okta/samples-java-spring/trunk/custom-login

| | If you don’t have svn installed, go here and click the Download button. |


Create an OIDC App on Okta

If you already have an Okta Developer account, log in to it. If you don’t, create one at developer.okta.com/signup. After you’re logged in to your Okta dashboard, complete the following steps:

  1. From the Applications page, choose Add Application.
  2. On the Create New Application page, select Web.
  3. Give your app a memorable name, then click Done.

Your settings should look similar to the ones below.

You can specify your issuer (found under API > Authorization Servers), client ID, and client secret in custom-login/src/main/resources/application.yml as follows:

okta:
oauth2:
issuer: https://{yourOktaDomain}/oauth2/default
client-id: {yourClientID}
client-secret: {yourClientSecret}

However, it’s more secure if you store these values in environment variables and keep them out of source control (especially if your code is public).

export OKTA_OAUTH2_ISSUER=https://{yourOktaDomain}/oauth2/default
export OKTA_OAUTH2_CLIENT_ID={yourClientID}
export OKTA_OAUTH2_CLIENT_SECRET={yourClientSecret}

| | I recommend adding the above exports to a .okta.env file in the root of your project and adding *.env to .gitignore. Then run source .okta.env before you start your app. |

After making these changes, you can start the app using ./mvnw. Open your browser to http://localhost:8080, click Login and you should be able to authenticate. If you still have your browser set to use Spanish first, you’ll see that the Sign-In Widget automatically renders in Spanish.

This works because Spring auto-enables AcceptHeaderLocaleResolver.

Add i18n Messages and Sync Locales

It seems like things are working smoothly at this point. However, if you add a LocaleChangeInterceptor, you’ll see that changing the language doesn’t change the widget’s language. To see this in action, create an MvcConfigurer class in custom-login/src/main/java/com/okta/spring/example.

package com.okta.spring.example;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;

@Configuration
public class MvcConfigurer implements WebMvcConfigurer {

@Bean
public LocaleResolver localeResolver() {
    return new CookieLocaleResolver();
}

@Bean
public LocaleChangeInterceptor localeInterceptor() {
    LocaleChangeInterceptor localeInterceptor = new LocaleChangeInterceptor();
    localeInterceptor.setParamName("lang");
    return localeInterceptor;
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(localeInterceptor());
}

}

Restart the custom-login app and navigate to http://localhost:8080/?lang=en. If you click the login button, you’ll see that the widget is still rendered in Spanish. To fix this, crack open LoginController and add language as a model attribute. You might notice this determines the language by injecting LocaleResolver in the constructor and using localeResolver.resolveLocale(request).

package com.okta.spring.example.controllers;

import org.springframework.web.servlet.LocaleResolver;
...

@Controller
public class LoginController {

...
private static final String LANGUAGE = "language";

private final OktaOAuth2Properties oktaOAuth2Properties;
private final LocaleResolver localeResolver;

public LoginController(OktaOAuth2Properties oktaOAuth2Properties, LocaleResolver localeResolver) {
    this.oktaOAuth2Properties = oktaOAuth2Properties;
    this.localeResolver = localeResolver;
}

@GetMapping(value = "/custom-login")
public ModelAndView login(HttpServletRequest request,
                          @RequestParam(name = "state", required = false) String state)
                          throws MalformedURLException {

    ...
    mav.addObject(LANGUAGE, localeResolver.resolveLocale(request));

    return mav;
}

...

}

Then modify src/main/resources/templates/login.html and add a config.language setting that reads this value.

config.redirectUri = /[[${redirectUri}]]/ '{redirectUri}';
config.language = /[[${language}]]/ '{language}';

Restart everything, go to http://localhost:8080/?lang=en, click the login button and it should now render in English.


Add Internationalization Bundles for Thymeleaf

To make it a bit more obvious that changing locales is working, create messages.properties in src/main/resources, and specify English translations for keys.

hello=Hello
welcome=Welcome home, {0}!

Create messages_es.properties in the same directory, and provide translations.

hello=Hola
welcome=¡Bienvenido a casa {0}!

Open src/main/resources/templates/home.html and change <p>Hello!</p> to the following:

<p th:text="#{hello}">Hello!</p>

Change the welcome message when the user is authenticated too. The {0} value will be replaced by the arguments passed into the key name.

<p th:text="#{welcome(${#authentication.name})}">Welcome home,
<span th:text="${#authentication.name}">Joe Coder</span>!</p>

Restart Spring Boot, log in, and you should see a welcome message in your chosen locale.

You gotta admit, this is sah-weet! There’s something that tells me it’d be even better if the locale is set from your user attributes in Okta. Let’s make that happen!

Use the User’s Locale from Okta

To set the locale from the user’s information in Okta, create an OidcLocaleResolver class in the same directory as MvcConfigurer.

package com.okta.spring.example;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;

import javax.servlet.http.HttpServletRequest;
import java.util.Locale;

@Configuration
public class OidcLocaleResolver extends CookieLocaleResolver {
private final Logger logger = LoggerFactory.getLogger(OidcLocaleResolver.class);

@Override
public Locale resolveLocale(HttpServletRequest request) {
    SecurityContext securityContext = SecurityContextHolder.getContext();
    if (securityContext.getAuthentication().getPrincipal() instanceof OidcUser) {
        OidcUser user = (OidcUser) securityContext.getAuthentication().getPrincipal();
        logger.info("Setting locale from OidcUser: {}", user.getLocale());
        return Locale.forLanguageTag(user.getLocale());
    } else {
        return request.getLocale();
    }
}

}

Then update MvcConfigurer to use this class:

@Bean
public LocaleResolver localeResolver() {
return new OidcLocaleResolver();
}

Try it out by restarting, navigating to http://localhost:8080/?lang=es, and authenticating. You should land back on your app’s homepage with English (or whatever your user’s locale is) as the language.

Yeehaw! Feels like Friday, doesn’t it?! 😃

i18n in JavaScript with Angular, React, and Vue

In this post, you saw how to internationalize a basic Java program and a Spring Boot app. We barely scratched the service on how to do i18n in JavaScript. The good news is I have an excellent example of i18n for JavaScript apps.

JHipster is powered by Spring Boot and includes localization for many languages on the server and the client. It supports three awesome front-end frameworks: Angular, React, and Vue. It uses the following libraries to lazy-load JSON files with translations on the client. I invite you to check them out if you’re interested in doing i18n in JavaScript (or TypeScript).


Originally published by Matt Raible at https://developer.okta.com

Learn More

Full Stack Web Development with Angular and Spring MVC

Build a Basic App with Spring Boot and JPA using PostgreSQL

Introducing TensorFlow.js: Machine Learning in Javascript

5 Javascript (ES6+) features that you should be using in 2019

ES5 to ESNext — here’s every feature added to JavaScript since 2015

Full Stack Developers: Everything You Need to Know

Build a Simple CRUD App with Spring Boot and Vue.js


14 Tips for Writing Spring MVC Controllers

14 Tips for Writing Spring MVC Controllers

Here are 14 helpful tips for writing Spring MVC Controllers. Take a look!

In this article, I'm going to share with you some of the fundamental techniques and best practices for writing a controller class with the Spring MVC framework. Typically, in Spring MVC, we write a controller class to handle requests coming from the client.

Then, the controller invokes a business class to process business-related tasks, and then redirects the client to a logical view name, which is resolved by Spring’s dispatcher servlet in order to render results or output. That completes a round trip of a typical request-response cycle.

Here are summary of the tips you will learn throughout this article:

  1. Using the @Controller stereotype
  2. Implementing the Controller Interface
  3. Extending the AbstractController Class
  4. Specifying URL Mapping for Handler Method
  5. Specifying HTTP Request Methods for Handler Method
  6. Mapping Request Parameters to Handler Method
  7. Returning Model And View
  8. Putting Objects into the Model
  9. Redirection in Handler Method
  10. Handling Form Submission and Form Validation
  11. Handling File Upload
  12. Autowiring Business Classes in the Controller
  13. Accessing HttpServletRequest and HttpServletResponse
  14. Following the Single Responsibility Principle
1. Using the @Controller Stereotype

This is the simplest way to create a controller class that can handle one or multiple requests. Just by annotating a class with the @Controllerstereotype, for example:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HomeController {

    @RequestMapping("/")
    public String visitHome() {

        // do something before returning view name

        return "home";
    }
}

As you can see, the visitHome() method handles requests coming to the application’s context path (/) by redirecting to the view named home.

NOTE: the **@Controller **stereotype can only be used when annotation-driven is enabled in Spring’s configuration file:

<annotation-driven />

When annotation-driven is enabled, the Spring container automatically scans for classes under the package specified in the following statement:

<context:component-scan base-package="net.codejava.spring" />

The classes annotated by the @Controllerannotation are configured as controllers. This is most preferable because of its simplicity: There's no need to declare beans for controllers in the configuration file.

NOTE: By using the @Controllerannotation, you can have a multi-actions controller class that is able to serve multiple different requests. For example:

@Controller
public class MultiActionController {

    @RequestMapping("/listUsers")
    public ModelAndView listUsers() {

    }

    @RequestMapping("/saveUser")
    public ModelAndView saveUser(User user) {

    }

    @RequestMapping("/deleteUser")
    public ModelAndView deleteUser(User user) {

    }
}

As you can see in the above controller class, there are three handler methods that process three different requests /listUsers, /saveUser, and /deleteUser, respectively.

2. Implementing the Controller Interface

Another (and maybe classic) way of creating a controller in Spring MVC is having a class implement the Controller interface. For example:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class MainController implements Controller {

    @Override
    public ModelAndView handleRequest(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        System.out.println("Welcome main");
        return new ModelAndView("main");
    }
}

The implementing class must override the handleRequest() method, which will be invoked by the Spring dispatcher servlet when a matching request comes in. The request URL pattern handled by this controller is defined in the Spring’s context configuration file as follows:

<bean name="/main" class="net.codejava.spring.MainController" />

However, a drawback of this approach is that the controller class cannot handle multiple request URLs.

3. Extending the AbstractController Class

If you want to easily control the supported HTTP methods, session, and content caching. having your controller class extended the AbstractController class is ideal. Consider the following example:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

public class BigController extends AbstractController {

    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        System.out.println("You're big!");
        return new ModelAndView("big");
    }
}

This creates a single-action controller with configurations regarding the supported methods, session, and caching, which can then be specified in the bean declaration of the controller. For example:

<bean name="/big" class="net.codejava.spring.BigController">
    <property name="supportedMethods" value="POST"/>
</bean>

This configuration indicates that only the POST method is supported by this controller’s hander method. For other configuration (session, caching), see AbstractController.

Spring MVC also offers several controller classes designed for specific purposes, including:

4. Specifying URL Mapping for the Handler Method

This is the mandatory task you must do when coding a controller class, which is designed for handling one or more specific requests. Spring MVC provides the @RequestMapping annotation, which is used for specifying URL mapping. For example:

@RequestMapping("/login")

That maps the URL pattern /login to be handled by the annotated method or class. When this annotation is used at the class level, the class becomes a single-action controller. For example:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/hello")
public class SingleActionController {

    @RequestMapping(method = RequestMethod.GET)
    public String sayHello() {
        return "hello";
    }
}

When the @RequestMapping annotation is used at the method level, you can have a multi-action controller. For example:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {

    @RequestMapping("/listUsers")
    public String listUsers() {
        return "ListUsers";
    }

    @RequestMapping("/saveUser")
    public String saveUser() {
        return "EditUser";
    }

    @RequestMapping("/deleteUser")
    public String deleteUser() {
        return "DeleteUser";
    }
}

The @RequestMapping annotation can be also used for specifying multiple URL patterns to be handled by a single method. For example:

@RequestMapping({"/hello", "/hi", "/greetings"})

In addition, this annotation has other properties that may be useful in some cases, e.g. the method property which is covered in the next section.

5. Specifying HTTP Request Methods for the Handler Method

You can specify which HTTP method (GET, POST, PUT, …) is supported by a handler method using the method property of the @RequestMapping annotation. Here’s an example:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class LoginController {

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String viewLogin() {
        return "LoginForm";
    }

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String doLogin() {
        return "Home";
    }
}

As you can see, this controller has two methods that handle the same URL pattern /login, but the former is for the GET method and the latter is for the POST method.

For more information about using the @RequestMapping annotation, see @RequestMapping annotation.

6. Mapping Request Parameters to Handler Method

One of the cool features of Spring MVC is that you can retrieve request parameters as regular parameters of the handler method by using the @RequestParam annotation. This is a good way to decouple the controller from the HttpServletRequest interface of the Servlet API.

Let’s look at various examples. Consider the following method:

@RequestMapping(value = "/login", method = RequestMethod.POST)
public String doLogin(@RequestParam String username,
                      @RequestParam String password) {

}

Spring binds the method parameters username and password to the HTTP request parameters with the same names. That means you can invoke a URL as follows (if the request method is GET):

http://localhost:8080/spring/login?username=scott&password=tiger

Type conversion is also done automatically. For example, if you declare a parameter of type integer as follows:

@RequestParam int securityNumber

Then, Spring will automatically convert value of the request parameter (String) to the specified type (integer) in the handler method.

In case the parameter name is different than the variable name, you can specify the actual name of the parameter as follows:

@RequestParam("SSN") int securityNumber

The @RequestParam annotation also has two additional attributes, which might be useful in some cases. Therequiredattribute specifies whether the parameter is mandatory or not. For example:

@RequestParam(required = false) String country

That means the parameter country is optional; hence, it can be missing from the request. In the above example, the variable country will be null if there is no such parameter present in the request.

Another attribute is defaultValue, which can be used as a fallback value when the request parameter is empty. For example:

@RequestParam(defaultValue = "18") int age

Spring also allows us to access all parameters as a Map object if the method parameter is of type Map<String, String>. For example:

doLogin(@RequestParam Map<String, String> params)

Then the map params contains all request parameters in the form of key-value pairs. For more information about using the @RequestParam annotation, see @RequestParam annotation.

7. Returning Model and View

After business logic is processed, a handler method should return a view, which is then resolved by the Spring’s dispatcher servlet. Spring allows us to return either a String or a ModelAndView object from the handler method. In the following example, the handler method returns a String and represents a view named LoginForm:

@RequestMapping(value = "/login", method = RequestMethod.GET)
public String viewLogin() {
    return "LoginForm";
}

That’s the simplest way of returning a view name. But if you want to send additional data to the view, you must return a ModelAndView object. Consider the following handler method:

@RequestMapping("/listUsers")
public ModelAndView listUsers() {

    List<User> listUser = new ArrayList<>();
    // get user list from DAO...

    ModelAndView modelView = new ModelAndView("UserList");
    modelView.addObject("listUser", listUser);

    return modelView;
}

As you can see, this handler method returns a ModelAndView object that holds the view name UserList and a collection of User objects, which can be used in the view.

Spring is also very flexible, as you can declare the ModelAndView object as a parameter of the handler method instead of creating a new one. Thus, the above example can be re-written as follows:

@RequestMapping("/listUsers")
public ModelAndView listUsers(ModelAndView modelView) {

    List<User> listUser = new ArrayList<>();
    // get user list from DAO...

    modelView.setViewName("UserList");
    modelView.addObject("listUser", listUser);

    return modelView;
}

You can learn more about the ModelAndView class by visiting: ModelAndView class.

8. Putting Objects Into the Model

In an application that follows the MVC architecture, the controller (C) should pass data into the model (M), which is then used in the view (V). As we see in the previous example, the addObject() method of the ModelAndView class is for putting an object to the model, in form of name-value pair:

modelView.addObject("listUser", listUser);
modelView.addObject("siteName", new String("CodeJava.net"));
modelView.addObject("users", 1200000);

Again, Spring is very flexible. You can declare a parameter of type Map in the handler method; Spring uses this map to store objects for the model. Let’s see another example:

@RequestMapping(method = RequestMethod.GET)
public String viewStats(Map<String, Object> model) {
    model.put("siteName", "CodeJava.net");
    model.put("pageviews", 320000);

    return "Stats";
}

This is even simpler than using the ModelAndView object. Depending on your taste, you can use either Map or ModelAndView object. Thanks for the flexibility of Spring.

9. Redirection in Handler Method

In case you want to redirect the user to another URL if a condition is met, just append redirect:/ before the URL. The following code snippet gives an example:

// check login status....

if (!isLogin) {
    return new ModelAndView("redirect:/login");
}

// return a list of Users

In the above code, the user will be redirected to the /login URL if it is not logged in.

10. Handling Form Submission and Form Validation

Spring makes it easy to handle form submission by providing the @ModelAttribute annotation for binding form fields to a form backing object, and the BindingResult interface for validating form fields. The following code snippet shows a typical handler method that is responsible for handling and validating form data:

@Controller
public class RegistrationController {

    @RequestMapping(value = "/doRegister", method = RequestMethod.POST)
    public String doRegister(
        @ModelAttribute("userForm") User user, BindingResult bindingResult) {

        if (bindingResult.hasErrors()) {
            // form validation error

        } else {
            // form input is OK
        }

        // process registration...

        return "Success";
    }
}

Learn more about the @ModelAttribute annotation and the BindingResultinterface from Spring’s official documentation:

11. Handling File Upload

Spring also makes it easy to handle file upload within a handler method, by automatically binding upload data to an array of CommonsMultipartFile objects. Spring uses Apache Commons FileUpload as the underlying multipart resolver.

The following code snippet shows how easy it is to get files uploaded from the client:

@RequestMapping(value = "/uploadFiles", method = RequestMethod.POST)
public String handleFileUpload(
        @RequestParam CommonsMultipartFile[] fileUpload) throws Exception {

    for (CommonsMultipartFile aFile : fileUpload){

        // stores the uploaded file
        aFile.transferTo(new File(aFile.getOriginalFilename()));

    }

    return "Success";
}

You can learn the complete solution for handling file upload with Spring MVC by following this Spring MVC File Upload Tutorial.

12. Autowiring Business Classes in the Controller

A controller should delegate the processing of business logic to relevant business classes. For this purpose, you can use the @Autowired annotation to let Spring automatically inject the actual implementation of a business class to the controller. Consider the following code snippet of a controller class:

@Controller
public class UserController {

    @Autowired
    private UserDAO userDAO;

    public String listUser() {
        // handler method to list all users
        userDAO.list();
    }

    public String saveUser(User user) {
        // handler method to save/update a user
        userDAO.save(user);
    }

    public String deleteUser(User user) {
        // handler method to delete a user
        userDAO.delete(user);
    }

    public String getUser(int userId) {
        // handler method to get a user
        userDAO.get(userId);
    }
}

Here, all business logic related to User management is provided by an implementation of the UserDAO interface. For example:

interface UserDAO {

    List<User> list();

    void save(User user);

    void checkLogin(User user);
}

By using the @Autowired annotation, the handler methods can delegate tasks to the business class, as we can see in the above example:

List<User> listUser = userDAO.list();

For more information about the @Autowired annotation, see Annotation Type Autowired.

13. Accessing HttpServletRequest and HttpServletResponse

In some cases, you need to directly access the HttpServletRequest or HttpServletResponse objects within a handler method. By the flexibility of Spring, just add a relevant parameter to the handler method. For example:

@RequestMapping("/download")
public String doDownloadFile(
        HttpServletRequest request, HttpServletResponse response) {

    // access the request

    // access the response

    return "DownloadPage";
}

Spring detects and automatically injects the HttpServletRequest and HttpServletResponse objects into the method. Then, you can access the request and response such as getting InputStream, OutputStream, or returning a specific HTTP code.

14. Following the Single Responsibility Principle

Finally, there are two good practices you should follow when designing and coding controllers in Spring MVC:

  • A controller class should not execute business logic. Instead, it should delegate business processing to relevant business classes. This keeps the controller focusing on its designed responsibility is to control workflows of the application. For example:
@Controller
public class UserController {

    @Autowired
    private UserDAO userDAO;

    public String listUser() {
        // handler method to list all users
        userDAO.list();
    }

    public String saveUser(User user) {
        // handler method to save/update a user
        userDAO.save(user);
    }

    public String deleteUser(User user) {
        // handler method to delete a user
        userDAO.delete(user);
    }

    public String getUser(int userId) {
        // handler method to get a user
        userDAO.get(userId);
    }
}
  • Create each separate controller for each business domain. For example, UserController for controlling workflows of the user management, OrderController for controlling workflows of order processing, etc. For example:
@Controller
public class UserController {

}

@Controller
public class ProductController {

}

@Controller
public class OrderController {

}

@Controller
public class PaymentController {

}

There you have it! I have shared 14 tips that will help you write controller classes in Spring MVC properly and efficiently. However, that’s not the end. If you have other tips or suggestions, feel free to share your thoughts in the comments.