Spring MVC Login Application

Technology Stack
Project Structure

Screen Shot 2020-02-23 at 8.11.20 PM

pom.xml

Add the below in pom.xml

  • spring-boot-starter-parent – add this as parent
  • mysql-connector-java – needed for mysql driver and other related classes.

Add the below spring boot starters

  • spring-boot-starter-web – needed for spring mvc
  • spring-boot-starter-thymeleaf – needed for thymeleaf
  • spring-boot-starter-data-jpa – needed for spring data jpa
 <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath />
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
</dependencies>
Domain Layer

Define the Account Entity here.

package com.spring.mvc.model;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Account {
public Account() {}
@Id
private String username;
public Account(String username, String password, String firstname, String lastname) {
this.username = username;
this.password = password;
this.firstname = firstname;
this.lastname = lastname;
}
private String password;
private String firstname;
private String lastname;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
}
Repository Layer

Define the Spring Data JPA Interface which extends CrudRepository.

Please visit Spring Data JPA+Spring Boot+MySQL for better understanding of Spring Data JPA.

package com.spring.mvc.repository;

import org.springframework.data.repository.CrudRepository;

import com.spring.mvc.model.Account;

public interface AccountRepository extends CrudRepository<Account, String>{

}

Service Layer
Define Service Interface
package com.spring.mvc.service;
import com.spring.mvc.model.Account;
public interface AccountService {
public Account createAccount(Account account);
public Account findAccount(String username, String password);
}
Define Service Implementation
package com.spring.mvc.service;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.spring.mvc.model.Account;
import com.spring.mvc.repository.AccountRepository;
@Service
public class AccountServiceImpl implements AccountService{
@Autowired
    private AccountRepository repository;
@Override
public Account createAccount(Account account) {
if (repository.existsById(account.getUsername())) {
return null;
}
return repository.save(account);
}
@Override
public Account findAccount(String username, String password) {
Optional<Account> dbAccount = repository.findById(username);
if (dbAccount.isPresent() && dbAccount.get().getPassword().equals(password)) {
return dbAccount.get();
}
return null;
}
}
Controller Layer
package com.spring.mvc.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.spring.mvc.model.Account;
import com.spring.mvc.service.AccountService;
@Controller
public class ApplicationController {
@Autowired
private AccountService accountService;
@GetMapping(“/”)
public String landingPage(Model model) {
return “landing”;
}
@PostMapping(“/login”)
public String welcome(@RequestParam(“username”) String username, @RequestParam(“password”) String password,
Model model) {
if(username ==  null || username.isEmpty()) {
model.addAttribute(“errormessage”, “Please enter username”);
return landingPage(model);
}
if(password ==  null || password.isEmpty()) {
model.addAttribute(“password”, “Please enter password”);
return landingPage(model);
}
Account account = accountService.findAccount(username, password);
if (account == null) {
model.addAttribute(“errormessage”, “Your username and password combination is not correct”);
model.addAttribute(“username”, username);
model.addAttribute(“password”, password);
return landingPage(model);
}
model.addAttribute(“account”, account);
return “welcome”;
}
@GetMapping(“/registration”)
public String registration(Model model) {
return “registration”;
}
@PostMapping(“/createAccount”)
public String createAccount(Model model,@RequestParam(“username”) String username, 
@RequestParam(“password”) String password,@RequestParam(“againpassword”) String againpassword, 
@RequestParam(“firstname”) String firstname,@RequestParam(“lastname”) String lastname) {
boolean reloadPage = false;
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password) || StringUtils.isEmpty(againpassword)
|| StringUtils.isEmpty(firstname) || StringUtils.isEmpty(lastname)) {
reloadPage = true;
model.addAttribute(“errormessage”, “All fields are mandatory.”);
}
if (!reloadPage && !password.equals(againpassword)) {
reloadPage = true;
model.addAttribute(“errormessage”, “Password does not match”);
}
if (!reloadPage) {
Account account = new Account(username, password, firstname, lastname);
Account dbAccount = accountService.createAccount(account);
if (dbAccount == null) {
reloadPage = true;
model.addAttribute(“errormessage”, “Account already exists for the username”);
}
}
if (reloadPage) {
model.addAttribute(“username”, username);
model.addAttribute(“password”, password);
model.addAttribute(“againpassword”, againpassword);
model.addAttribute(“firstname”, firstname);
model.addAttribute(“lastname”, lastname);
return registration(model);
}
model.addAttribute(“message”, “Account successfully created. Please login.”);
return landingPage(model);
}
}
Application class annotated with @SpringBootApplication

Define datasource, entityManagerFactory and other beans here.

package com.spring.mvc.config;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication(scanBasePackages = {“com.spring.mvc.controller”,”com.spring.mvc.service”})
@EnableTransactionManagement
@EnableJpaRepositories(“com.spring.mvc.repository”)
@PropertySource(“classpath:database.properties”)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Autowired
Environment environment;
private final String URL = “url”;
private final String USER = “dbuser”;
private final String PASSWORD = “dbpassword”;
private final String PROPERTY_SHOW_SQL = “hibernate.show_sql”;
private final String PROPERTY_DIALECT = “hibernate.dialect”;
@Bean
DataSource dataSource() {
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setUrl(environment.getProperty(URL));
driverManagerDataSource.setUsername(environment.getProperty(USER));
driverManagerDataSource.setPassword(environment.getProperty(PASSWORD));
return driverManagerDataSource;
}
@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lfb = new LocalContainerEntityManagerFactoryBean();
lfb.setDataSource(dataSource());
lfb.setPersistenceProviderClass(HibernatePersistenceProvider.class);
lfb.setPackagesToScan(“com.spring.mvc.model”);
lfb.setJpaProperties(hibernateProps());
return lfb;
}
Properties hibernateProps() {
Properties properties = new Properties();
properties.setProperty(PROPERTY_DIALECT, environment.getProperty(PROPERTY_DIALECT));
properties.setProperty(PROPERTY_SHOW_SQL, environment.getProperty(PROPERTY_SHOW_SQL));
return properties;
}
@Bean
JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
}
database.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/testchema
dbuser=root
dbpassword=root
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
View Layer – templates

Thymeleaf is a default template used by Spring Boot.
By default, Spring Boot looks for the templates in src/main/resources/templates location.

Add the html files inside src/main/resources/templates

landing.html

<html xmlns:th=″http://www.thymeleaf.org″>

<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″>
<title>Application</title>
<link rel=”stylesheet” href=″https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css″>

</head>
<body style=”width:50%;margin: 20px;padding: 20px;”>
<h3>Spring MVC Application using Spring Boot and Thymeleaf</h3>
<p style=”color: red;”>[[${errormessage}]]</p>
<p style=”color: green;”>[[${message}]]</p>
<div style=”margin: 20px;border: 1px solid blue;padding: 20px;”>
<div class=”form” style=”margin: 20px;padding: 20px;”>
<h4>Login</h4>
<form action=”login” method=”post”>
<table class=”table table-bordered”>
<tr>
<td>Please Enter Your UserName</td>
<td><input id=”username” name=”username” th:value=”${username}”></td>
</tr>
<tr>
<td>Please Enter Your Password</td>
<td><input id=”password” name=”password” type=”password” th:value=”${password}”></td>
</tr>
</table>
<input type=”submit” value=”Submit”>
</form>
</div>

<div class=”form”>
<form action=”/registration” method=”get”>
<table>
<tr>
<td><input type=”submit” value=”Registration”></td>
</tr>
</table>
</form>
</div>
</div>
</body>
</html>

welcome.html

<html xmlns:th=″http://www.thymeleaf.org″>

<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″>
<title>Application</title>
<link rel=”stylesheet” href=″https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css″>

</head>
<body style=”width:50%;”>
<div style=”margin: 20px;padding: 20px;”>
<h3>Spring MVC Application using Spring Boot and Thymeleaf</h3>
<div class=”form” style=”margin: 20px;border: 1px solid blue;padding: 20px;”>

<h4>Your Details are mentioned below:</h4>
<table class=”table table-bordered” style=”padding: 20px;”>
<tr>
<td>UserName</td>
<td>[[${account.username}]]</td>
</tr>
<tr>
<td>FirstName</td>
<td>[[${account.firstname}]]</td>
</tr>
<tr>
<td>LastName</td>
<td>[[${account.lastname}]]</td>
</tr>
</table>
<div class=”form”>
<form action=”/” method=”get”>
<table>
<tr>
<td><input type=”submit” value=”Logout”></td>
</tr>
</table>
</form>
</div>
</div>
</div>
</body>
</html>

registration.html

<html xmlns:th=″http://www.thymeleaf.org″>

<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″>
<title>Application</title>
<link rel=”stylesheet” href=″https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css″>

</head>

<html xmlns:th=″http://www.thymeleaf.org″>

<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″>
<title>Application</title>
<link rel=”stylesheet” href=″https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css″>

</head>

<body style=”width:50%;margin: 20px;padding: 20px;”>
<h3>Spring MVC Application using Spring Boot and Thymeleaf</h3>
<p style=”color: red;”>[[${errormessage}]]</p>
<div style=”margin: 20px;border: 1px solid blue;padding: 20px;”>
<div class=”form” style=”margin: 20px;padding: 20px;”>
<h4>Registration</h4>
<form action=”createAccount” method=”post”>
<table class=”table table-bordered”>
<tr>
<td>Please Enter Your UserName</td>
<td><input id=”username” name=”username” th:value=”${username}”></td>
</tr>
<tr>
<td>Please Enter Your Password</td>
<td><input id=”password” name=”password” type=”password” th:value=”${password}”></td>
</tr>
<tr>
<td>Please Enter Your Password Again</td>
<td><input id=”againpassword” name=”againpassword” type=”password” th:value=”${againpassword}”></td>
</tr>
<tr>
<td>Please Enter Your First Name</td>
<td><input id=”firstname” name=”firstname” th:value=”${firstname}”></td>
</tr>
<tr>
<td>Please Enter Your last Name</td>
<td><input id=”lastname” name=”lastname” th:value=”${lastname}”></td>
</tr>

</table>
<input type=”submit” value=”Submit”>
</form>
</div>
<div class=”form”>
<form action=”/” method=”get”>
<table>
<tr>
<td><input type=”submit” value=”Go to Login”></td>
</tr>
</table>
</form>
</div>
</div>

</body>
</html>

Running Application

Execute the main method of Application.class and then hit http://localhost:8080

Screen Shot 2020-02-23 at 8.41.34 PM
landing page

 Enter some random values and click on Submit

Screen Shot 2020-02-23 at 8.41.50 PMScreen Shot 2020-02-23 at 8.42.35 PM

Enter valid values now  and click on Submit

Screen Shot 2020-02-23 at 8.42.53 PM

Screen Shot 2020-02-23 at 8.43.15 PM
welcome page

Click on Logout and it will go back to landing page

Screen Shot 2020-02-23 at 8.43.24 PM

Registration Flow

Click on Registration Button

Screen Shot 2020-02-23 at 8.43.58 PM
Registration Page

Screen Shot 2020-02-23 at 8.44.06 PMScreen Shot 2020-02-23 at 8.44.41 PMScreen Shot 2020-02-23 at 8.44.47 PM

Leave a Reply

Your email address will not be published. Required fields are marked *