Monitoring Spring boot applications using actuator and prometheus

In this article ,we will see how we can monitor spring boot applications using actuator spring boot project and prometheus tool .

Prometheus

Prometheus is a time-series monitoring application written in Go. It can run on a server, in a docker container, or as part of a Kubernetes cluster (or something similar). Prometheus collects, stores, and visualizes time-series data so that you can monitor your systems. You can tell Prometheus exactly where to find metrics by configuring a list of “scrape jobs”. Applications that are being monitored can provide metrics endpoints to Prometheus using any one of the many client libraries available; additionally, separate exporters can gather metrics from applications to make them available in Prometheus. Metrics get stored locally for 15 days, by default, and any Prometheus server can scrape another one for data. Additionally, remote storage is another option for Prometheus data – provided there is a reliable remote storage endpoint.

Benefits:

  • The option of “service discovery” allows Prometheus to keep track of all current endpoints effortlessly.
  • Outages are quickly detected .
  • The PromQL query language is incredibly flexible and Turing-complete.
  • There’s also a very low load on the services monitored (metrics get stored in memory as they get generated), allowing fewer resources to get used.
  • Additionally, Prometheus users can control traffic volumes, access metrics in the browser, and allow for easy reconfiguration.

Part 1: Spring boot application configuration

We will create a simple spring boot REST application which will expose the metrics to prometheus. Please find below project structure of application –

Project Structure

Below is the pom.xml required for project –

<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.db</groupId>
    <artifactId>spring-boot-prometheus</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.9.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-prometheus</artifactId>
        </dependency>

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

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

</project>

We need spring-boot-starter-actuator dependency ,this would expose the endpoints of our application and makes it available to prometheus server. You can run the application and check the endpoints exposed by actuator by hitting below link in browser –

http://localhost:8081/actuator

Micrometer

micrometer-registry-prometheus dependency is required to register metrics with prometheus server. It exposes Actuator metrics to external monitoring systems such as Prometheus, Netflix Atlas, AWS Cloudwatch, and many more.

Similarly, Micrometer automatically exposes /actuator/metrics data into something your monitoring system can understand. All you need to do is include that vendor-specific micrometer dependency in your application.

Micrometer is a separate open-sourced project and is not in the Spring ecosystem, so we have to explicitly add it as a dependency. Since we will be using Prometheus, let’s add it’s specific dependency in our pom.xml:

Part 2: Prometheus Server Configuration

For this example , i will be installing portable prometheus on local system . You can download the prometheus setup from official prometheus website as below –

https://prometheus.io/download/

You need to make below changes in prometheus.yml file of prometheus configuration to scrape the metrices your application .Please add below job to scrape the metrices of your application –

 # Details to connect Prometheus with Spring Boot actuator end point to scrap the data
  # The job name is added as a label `job=` to any time series scraped from this config.
  - job_name: 'spring-actuator'
   
    # Actuator end point to collect the data. 
    metrics_path: '/actuator/prometheus'

    #How frequently to scape the data from the end point
    scrape_interval: 5s

    #target end point. We are using the Docker, so local host will not work. You can change it with
    #localhost if not using the Docker.
    static_configs:
    - targets: ['192.168.43.33:8081']

Run the prometheus server by double clicking prometheus.exe flie .

Now prometheus console will open and it will strat gathering the metrices of your application. You can access the prometheus server in browser using http://localhost:9090

Targets for metrics
Classes loaded in JVM prometheus metrics
Number of Threads in different states

You can gather the metrices of your application by selecting the various parameters provided by prometheus like –

  • jvm_classes_loaded_classes
  • jvm_threads_live_threads
  • jvm_threads_states_threads
  • jvm_threads_states_threads
  • tomcat_global_request_seconds_count

These parameters are useful to monitor your systems. In the next article, we will create a prometheus server using docker and expose the metrices.

Github Downlod Link:

Spring Boot profiles

In this article, we will see profiles for spring boot project –

Github Link –

 

What are Profiles?

Every enterprise application has many environments, like:

Dev | Test | Stage | Prod | UAT / Pre-Prod

Each environment requires a setting that is specific to them. For example, in DEV, we do not need to constantly check database consistency. Whereas in TEST and STAGE, we need to. These environments host specific configurations called Profiles.

How do we Maintain Profiles?

In spring boot application, we need different configurations for different environments. We have application.properties file to maintain application specific properties. In order to create profiles for different environments , we need to create various properties files as below –

DEV – application-dev.properties

TEST– application-test.properties

PROD – application-prod.properties

Step 1: Create below project structure in IntelliJ

Step 2: We are creating 3 different property files for below mentioned environments –

DEV – application-dev.properties

TEST– application-test.properties

PROD – application-prod.properties

Of course, the application.properties will remain as a master properties file, but if we override any key in the profile-specific file, the latter will gain precedence.

Step 3: Specify in application.properties file which environment property needs to be loaded

spring.profiles.active=prod

spring.application.name=springbootprofiles

app.message = This is Application property for ${spring.application.name}

Here we are loading PROD properties when application gets booted.

Step 4: Define DB configuration properties for in respective properties file and add code in DBConfiguration.class to pick the appropriate settings.

package com.myjavablog.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

@Configuration
@ConfigurationProperties("spring.datasource")
public class DBConfiguration {

    private String driverClassName;
    private String url;
    private String username;
    private String password;

    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    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;
    }

    @Profile("dev")
    @Bean
    public String devDatabaseConnection() {
        System.out.println("DB connection for DEV - H2");
        System.out.println(driverClassName);
        System.out.println(url);
        return "DB connection for DEV - H2";
    }

    @Profile("test")
    @Bean
    public String testDatabaseConnection() {
        System.out.println("DB Connection to TEST -H2");
        System.out.println(driverClassName);
        System.out.println(url);
        return "DB Connection to TEST -H2";
    }

    @Profile("prod")
    @Bean
    public String prodDatabaseConnection() {
        System.out.println("DB Connection to PROD - H2");
        System.out.println(driverClassName);
        System.out.println(url);
        return "DB Connection to PROD - H2";
    }
}

This will load the properties file as per the spring.profiles.active property we have mentioned in application.properties file.

Step 5: Output

As per the application boot time logs below, you can see PROD database is loaded during application boot up.

2019-12-01 23:29:07.199  INFO 5728 --- [           main] rmationExtractorJdbcDatabaseMetaDataImpl : HHH000262: Table not found: user_details
2019-12-01 23:29:07.419  INFO 5728 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
DB Connection to PROD - H2
org.h2.Driver
jdbc:h2:mem:proddb;DB_CLOSE_ON_EXIT=FALSE
2019-12-01 23:29:09.147  INFO 5728 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot[email protected]e25951c: startup date [Sun Dec 01 23:28:49 IST 2019]; root of context hierarchy

You can connect to database as shown below –

Many To One(Uni-directional) Relational Mapping with Spring Boot + Spring Data JPA + H2 Database

In this tutorial , we will see Many To One mapping of two entities using Spring Boot and Spring Data JPA using H2 database.

GitHub Link 

Tools:

  • Spring Boot
  • Spring Data JPA
  • H2 Database
  • IntelliJ IDEA
  • Maven

We have two entities Student and Department. Many students are part of one Department (Many To One).

This is called Many To One mapping between two entities. For each of this entity, table will be created in database. So there will be two tables created in database.

create table address (id bigint generated by default as identity, name varchar(255), primary key (id));
create table student (id bigint generated by default as identity, mobile integer, name varchar(255), address_id bigint, primary key (id));
alter table student add constraint FKcaf6ht0hfw93lwc13ny0sdmvo foreign key (address_id) references address(id);

Each table has primary key as ID . Two tables has Many To One relationship between them as each department has many students in them.

STUDENT table has foreign key as DEPT_ID in it. So STUDENT is a child table and DEPARTMENT table is parent table in this relationship. FOREIGN KEY constraint adds below restrictions –

  1. We can’t add records in child table if there is no entry in parent table. Ex. You can’t add department ID reference in STUDENT table if department ID is not present in DEPARTMENT table.
  2. You can’t delete the records from parent table unless corresponding references are deleted from child table . Ex. You can’t delete the entry
    DEPARTMENT table unless corresponding students from STUDENT table are deleted . You can apply ON_DELETE_CASCADE with foreign key constraint if you want to delete students from STUDENT table automatically when department is deleted.
  3. If you want to insert a student into STUDENT table then corresponding department should already be present in DEPARTMENT table.
  4. When any department is updated in DEPARTMENT table then child table will also see the updated reference from parent table

Now we will see how can we form this relationship using Spring data JPA entities.

Step 1: Define all the dependencies required for this project

<?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">
<modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.myjavablog</groupId>
<artifactId>springboot-jpa-one-to-many-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-jpa-one-to-many-demo</name>
<description>Demo project for Spring Boot</description>
<pre><code><properties>
    <java.version>1.8</java.version>
</properties>

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

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

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.apache.tomcat</groupId>
                <artifactId>tomcat-jdbc</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <!--<scope>runtime</scope>-->
    </dependency>

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

    <!-- https://mvnrepository.com/artifact/colt/colt -->
    <dependency>
        <groupId>colt</groupId>
        <artifactId>colt</artifactId>
        <version>1.2.0</version>
    </dependency>

</dependencies>

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

spring-boot-starter-data-jpa – This jar is used to connect to database .It also has a support to provide different JPA implementations to interact with the database like Hibernate, JPA Repository, CRUD Repository etc.

h2 – Its used to create H2 database when the spring boot application boots up. Spring boot will read the database configuration from application.properties file and creates a DataSource out of it.

Step 2: Define the Model/Entity classes

Student.java

package com.myjavablog.model;

import org.springframework.stereotype.Repository;

import javax.annotation.Generated;
import javax.persistence.*;
import java.util.Optional;

@Entity
@Table(name = "STUDENT")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String name;

    @Column
    private int mobile;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "DEPT_ID")
    private Department department;

    public Long getId() {

        return id;
    }

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

    public String getName() {

        return name;
    }

    public void setName(String name) {

        this.name = name;
    }

    public int getMobile() {

        return mobile;
    }

    public void setMobile(int mobile) {

        this.mobile = mobile;
    }

    public Department getDepartment() {

        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }
}

Department.java

package com.myjavablog.model;

import javax.persistence.*;
import java.util.List;

@Entity
@Table(name = "DEPARTMENT")
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column
private String name;

public Long getId() {
    return id;
}

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

public String getName() {
    return name;
}

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

Below are the Annotations used while creating the entity classes –

Spring Data JPA Annotations –

  • @Entity – This annotation marks the class annotations.
  • @Table – This annotation creates table in database.
  • @Id – It creates primary key in table.
  • @GeneratedValue – It defines primary key generation strategy like AUTO,IDENTITY,SEQUENCE etc.
  • @Column It defines column property for table.
  • @ManyToOne – This annotation creates Many to One relationship between Student and Department entities. The cascade property (CascadeType.ALL) defines what should happen with child table records when something happens with parent table records. On DELETE, UPDATE , INSERT operations in parent table child table should also be affected. Only @ManyToOne annotation is enough to form one-to-many relationaship. This annotation is generally used in child entity to form Unidirectional relational mapping.
  • @JoinColumn – You can define column which creates foreign key in a table. In our example, DEPT_ID is a foreign key in STUDENT table which references to ID in DEPARTMENT table.

Step 3: Create the JPA repositories to query STUDENT and DEPARTMENT tables

StudentRepository and AddressRepository implemets JpaRepository which has methods to perform all CRUD operations. It has methods like save(), find(), delete(),exists(),count() to perform database operations.

package com.myjavablog.dao;

import com.myjavablog.model.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
public Student findByName(String name);
}

package com.myjavablog.dao;

import com.myjavablog.model.Address;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface AddressRepository extends JpaRepository<Address, Long>{
}

Step 4: Create the class BeanConfig to configure the bean for H2 database

This class creates a bean ServletRegistrationBean and autowires it to spring container. This bean actually required to access H2 database from console through browser.

package com.myjavablog;

import org.h2.server.web.WebServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfig {
@Bean
ServletRegistrationBean h2servletRegistration() {
    ServletRegistrationBean registrationBean = new ServletRegistrationBean(new WebServlet());
    registrationBean.addUrlMappings("/console/*");
    return registrationBean;
}
}

Step 5: Last but not the least, You need to define application properties.

#DATASOURCE (DataSourceAutoConfiguration & #DataSourceProperties)
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
#Hibernate
#The SQL dialect makes Hibernate generate better SQL for the chosen #database
spring.jpa.properties.hibernate.dialect =org.hibernate.dialect.H2Dialect
spring.datasource.driverClassName=org.h2.Driver
#Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update

logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE
server.port=8082
server.error.whitelabel.enabled=false

Step 6: Create the spring boot main file

package com.myjavablog;

import com.myjavablog.dao.DepartmentRepository;
import com.myjavablog.dao.StudentRepository;
import com.myjavablog.model.Department;
import com.myjavablog.model.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

import java.util.Arrays;

@SpringBootApplication
public class SpringbootJpaOneToManyDemoApplication implements CommandLineRunner {
@Autowired
private DepartmentRepository departmentRepository;

@Autowired
private StudentRepository studentRepository;

public static void main(String[] args) {

    SpringApplication.run(SpringbootJpaOneToManyDemoApplication.class, args);
}

@Override
public void run(String... args) throws Exception {
//Unidirectional Mapping
	Department department = new Department();
	department.setName("COMPUTER");
        departmentRepository.save(department);

	Student student = new Student();
		student.setDepartment(departmentRepository.findDepartmentByName("COMPUTER"));
		student.setName("Anup");
		student.setMobile(989911);
		Student student1 = new Student();
		student1.setDepartment(departmentRepository.findDepartmentByName("IT"));
		student1.setName("John");
		student1.setMobile(89774);
		studentRepository.saveAll(Arrays.asList(student,student1));
}
}

Step 7: Now run the application

Run the application as a java application or as spring boot application spring-boot:run

Once you run the application records will be inserted to tables as below –

Step 8: This application also has REST endpoints to expose the services as below –

Save department –

Add students under created department –

We can check database entries to cross verify –

One To Many (Bi-directional) Relational Mapping with Spring Boot + Spring Data JPA + H2 Database

In this tutorial , we will see One To Many mapping of two entities using Spring Boot and Spring Data JPA using H2 database.

GitHub Link 

Tools:

  • Spring Boot
  • Spring Data JPA
  • H2 Database
  • IntelliJ IDEA
  • Maven

We have two entities Student and Department. Many students are part of one Department (Many To One). And vice a versa i.e. each
Department has many students in it (One To Many) .

This is called One To Many and Many To One mapping between two entities. For each of this entity, table will be created in database. So there will be two tables created in database.

create table address (id bigint generated by default as identity, name varchar(255), primary key (id));
create table student (id bigint generated by default as identity, mobile integer, name varchar(255), address_id bigint, primary key (id));
alter table student add constraint FKcaf6ht0hfw93lwc13ny0sdmvo foreign key (address_id) references address(id);

Each table has primary key as ID . Two tables has One To Many relationship between them. All student has department associated with them and each
department has many students in them.

STUDENT  table has foreign key as DEPT_ID in it. So STUDENT is a child table and DEPARTMENT table is parent table in this relationship. FOREIGN KEY constraint adds below restrictions –

  1. We can’t add records in child table if there is no entry in parent table. Ex. You can’t add department ID reference in STUDENT table if department ID is not present in DEPARTMENT table.
  2. You can’t delete the records from parent table unless corresponding references are deleted from child table . Ex. You can’t delete the entry
    DEPARTMENT table unless corresponding students from STUDENT table are deleted . You can apply ON_DELETE_CASCADE with foreign key constraint if you want to delete students from STUDENT table automatically when department is deleted.
  3. If you want to insert a student into STUDENT table then corresponding department should already be present in DEPARTMENT table.
  4. When any department is updated in DEPARTMENT table then child table will also see the updated reference from parent table

Now we will see how can we form this relationship using Spring data JPA entities.

Step 1: Define all the dependencies required for this project

<?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">
<modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.myjavablog</groupId>
<artifactId>springboot-jpa-one-to-many-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-jpa-one-to-many-demo</name>
<description>Demo project for Spring Boot</description>
<pre><code><properties>
    <java.version>1.8</java.version>
</properties>

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

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

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.apache.tomcat</groupId>
                <artifactId>tomcat-jdbc</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <!--<scope>runtime</scope>-->
    </dependency>

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

    <!-- https://mvnrepository.com/artifact/colt/colt -->
    <dependency>
        <groupId>colt</groupId>
        <artifactId>colt</artifactId>
        <version>1.2.0</version>
    </dependency>

</dependencies>

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

spring-boot-starter-data-jpa – This jar is used to connect to database .It also has a support to provide different JPA implementations to interact with the database like Hibernate, JPA Repository, CRUD Repository etc.

h2 – Its used to create H2 database when the spring boot application boots up. Spring boot will read the database configuration from application.properties file and creates a DataSource out of it.

Step 2: Define the Model/Entity classes

Student.java

package com.myjavablog.model;

import org.springframework.stereotype.Repository;

import javax.annotation.Generated;
import javax.persistence.*;
import java.util.Optional;

@Entity
@Table(name = "STUDENT")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String name;

    @Column
    private int mobile;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "DEPT_ID")
    private Department department;

    public Long getId() {

        return id;
    }

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

    public String getName() {

        return name;
    }

    public void setName(String name) {

        this.name = name;
    }

    public int getMobile() {

        return mobile;
    }

    public void setMobile(int mobile) {

        this.mobile = mobile;
    }

    public Department getDepartment() {

        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }
}

Department.java

package com.myjavablog.model;

import javax.persistence.*;
import java.util.List;

@Entity
@Table(name = "DEPARTMENT")
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column
private String name;

@OneToMany(mappedBy = "department")
private List<Student> studentList;

public Long getId() {
return id;
}

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

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
public List<Student> getStudentList() {
return studentList;
}
public void setStudentList(List<Student> studentList) {
this.studentList = studentList;
}
}

Below are the Annotations used while creating the entity classes –

Spring Data JPA Annotations –

  • @Entity – This annotation marks the class annotations.
  • @Table – This annotation creates table in database.
  • @Id – It creates primary key in table.
  • @GeneratedValue – It defines primary key generation strategy like AUTO,IDENTITY,SEQUENCE etc.
  • @Column It defines column property for table.
  • @OneToMany – This annotation is used in the owning entity/Parent entity. This annotation is required in only if you want Bi-directional relational mapping.
  • @ManyToOne – This annotation creates Many to one relationship between Student and Department entities. The cascade property (CascadeType.ALL) defines what should happen with child table records when something happens with parent table records. On DELETE, UPDATE , INSERT operations in parent table child table should also be affected. Both @OneToMany and @ManyToOne annotations are required to form Bi-directional relational mapping.
  • @JoinColumn – You can define column which creates foreign key in a table. In our example, DEPT_ID is a foreign key in STUDENT table which references to ID in DEPARTMENT table.

Step 3: Create the JPA repositories to query STUDENT and DEPARTMENT tables

StudentRepository and AddressRepository implemets JpaRepository which has methods to perform all CRUD operations. It has methods like save(), find(), delete(),exists(),count() to perform database operations.

package com.myjavablog.dao;

import com.myjavablog.model.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
public Student findByName(String name);
}

package com.myjavablog.dao;

import com.myjavablog.model.Address;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface AddressRepository extends JpaRepository<Address, Long>{
}

Step 4: Create the class BeanConfig to configure the bean for H2 database

This class creates a bean ServletRegistrationBean and autowires it to spring container. This bean actually required to access H2 database from console through browser.

package com.myjavablog;

import org.h2.server.web.WebServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfig {
@Bean
ServletRegistrationBean h2servletRegistration() {
    ServletRegistrationBean registrationBean = new ServletRegistrationBean(new WebServlet());
    registrationBean.addUrlMappings("/console/*");
    return registrationBean;
}
}

Step 5: Last but not the least, You need to define application properties.

#DATASOURCE (DataSourceAutoConfiguration & #DataSourceProperties)
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
#Hibernate
#The SQL dialect makes Hibernate generate better SQL for the chosen #database
spring.jpa.properties.hibernate.dialect =org.hibernate.dialect.H2Dialect
spring.datasource.driverClassName=org.h2.Driver
#Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update

logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE
server.port=8082
server.error.whitelabel.enabled=false

Step 6: Create the spring boot main file

package com.myjavablog;

import com.myjavablog.dao.DepartmentRepository;
import com.myjavablog.dao.StudentRepository;
import com.myjavablog.model.Department;
import com.myjavablog.model.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

import java.util.Arrays;

@SpringBootApplication
public class SpringbootJpaOneToManyDemoApplication implements CommandLineRunner {
@Autowired
private DepartmentRepository departmentRepository;

@Autowired
private StudentRepository studentRepository;

public static void main(String[] args) {

    SpringApplication.run(SpringbootJpaOneToManyDemoApplication.class, args);
}

@Override
public void run(String... args) throws Exception {
    //Bi-directional mapping
		Department department1 = new Department();
		department1.setName("IT");

		//Students list
		Student student = new Student();
		student.setName("Danny");
		student.setMobile(33333);
		student.setDepartment(department1);
		Student student1 = new Student();
		student1.setName("Mark");
		student1.setMobile(11111);
		student1.setDepartment(department1);

		//department1.setStudentList(Arrays.asList(student,student1));
		department1.getStudentList().add(student);
		department1.getStudentList().add(student1);

		departmentRepository.save(department1);

		//Get the list of students from department
		Department department = departmentRepository.findDepartmentById(1l);

		for(Student s : department.getStudentList())
			System.out.println(s);
}
}

Step 7: Now run the application

Run the application as a java application or as spring boot application spring-boot:run

Once you run the application records will be inserted to tables as below –

Step 8: This application also has REST endpoints to expose the services as below –

Save department –

Add students under created department –

We can check database entries to cross verify –

Bi-directional Relational Mapping –

To create the bi-directional mapping between entities, we need to below changes in entities –

The idea with bidirectional one-to-many association is to allow you to keep a collection of child entities in the parent and enable you to persist and retrieve the child entities via the parent entity.

In our example, Department entity has list of students in it. So we can access all students from particular department.

//Bi-directional mapping
		Department department = new Department();
		department.setName("IT");

		//Students list
		Student student = new Student();
		student.setName("Danny");
		student.setMobile(33333);
		Student student1 = new Student();
		student1.setName("Mark");
		student1.setMobile(11111);

		department.setStudentList(Arrays.asList(student,student1));

		departmentRepository.save(department);

Hibernate automatically issues insert statements and saves the Students added to the Department.

Similarly, you could fetch Students via the Department entity like so –

    //Retrieve department
    Department department1 = departmentRepository.findDepartmentById(1l);

   // Retrieve students from Department
    System.out.println(department1.getStudentList());

When you write department1.getStudentList(), hibernate loads all the comments from the database if they are not already loaded.

Problems with bidirectional one-to-many mapping

  • A bidirectional mapping tightly couples the many-side of the relationship to the one-side.
  • In our example, If you load students via the Department entity, you won’t be able to limit the number of students loaded. That essentially means that you won’t be able to paginate.
  • If you load students via the Department  entity, you won’t be able to sort them based on different properties. You can define a default sorting order using @OrderColumn annotation but that will have performance implications.
  • You’ll have to face multiple times LazyInitializationException.

When can you use a bidirectional one-to-many mapping

A bidirectional one-to-many mapping might be a good idea if the number of child entities is limited.

Moreover, A bidirectional mapping tightly couples the many-side of the relationship to the one-side. Many times, this tight coupling is desired.

Example:

When you have to design an application for multiple choices questions then you should have two entities like Question and Choice. When you fetch the Question then Choices will also be fetched with that question. So Question and Choice has tight coupling between them.

So to decide between bidirectional and unidirectional mappings, you should think whether the entities have a tight coupling or not

One To One Relationship with Spring Boot + Spring Data JPA + H2 Database

In this tutorial , we will see One To One mapping of two entities using Spring Boot and Spring Data JPA using H2 database.

GitHub Link 

Tools:

  • Spring Boot
  • Spring Data JPA
  • H2 Database
  • IntelliJ IDEA
  • Maven
  • Lombok

We have two entities Student and Address. Each student has single address attached to him. And vice a versa i.e. each address is attached to student .

This is called One To One mapping between two entities. For each of this entity, table will be created in database. So there will be two tables created in database.

create table address (id bigint generated by default as identity, name varchar(255), primary key (id));
create table student (id bigint generated by default as identity, mobile integer, name varchar(255), address_id bigint, primary key (id));
alter table student add constraint FKcaf6ht0hfw93lwc13ny0sdmvo foreign key (address_id) references address(id);

Each table has primary key as ID . Two tables has One To One relationship between them. Each student has address associated with him and each address has one student.

STUDENT table has foreign key as ADDRESS_ID in it. So STUDENT is a child table and ADDRESS table is parent table in this relationship.

Now we will see how can we form this relationship using Spring data JPA entities.

Step 1: Define all the dependencies required for this project

<?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">
<modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.myjavablog</groupId>
<artifactId>spring-boot-data-jpa-one-to-one</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-data-jpa-one-to-one</name>
<description>Demo project for Spring Boot</description>
<pre><code><properties>
    <java.version>1.8</java.version>
</properties>

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

    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <!--<scope>runtime</scope>-->
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <!-- For JSP compilation -->
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
        <scope>provided</scope>
    </dependency>
</dependencies>

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

  • Lombok – We will be using lombok third party library to reduce boilerplate code for model/data objects, e.g., it can generate getters and setters for those object automatically by using Lombok annotations. The easiest way is to use the @Data annotation.
  • spring-boot-starter-data-jpa – This jar is used to connect to database .It also has a support to provide different JPA implementations to interact with the database like Hibernate, JPA Repository, CRUD Repository etc.
  • h2 – Its used to create H2 database when the spring boot application boots up. Spring boot will read the database configuration from application.properties file and creates a DataSource out of it.

Step 2: Define the Model/Entity

Student.java

package com.myjavablog.model;

import org.springframework.stereotype.Repository;

import javax.annotation.Generated;
import javax.persistence.*;
import java.util.Optional;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "STUDENT")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column
private String name;

@Column
private int mobile;

@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "ADDRESS_ID")
private Address address;


public Student(String name, int mobile, Address address) {
    this.name=name;
    this.mobile=mobile;
    this.address=address;
}

@Override
public String toString() {
    return "Student{" +
            "id=" + id +
            ", name='" + name + '\'' +
            ", mobile=" + mobile +                
            '}';
}
}

Address.java

package com.myjavablog.model;

import javax.persistence.*;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "ADDRESS")
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column
private String name;

@OneToOne(mappedBy = "address")
private Student student;

public Address(String name) {
    this.name =name;
}

@Override
public String toString() {
    return "Address{" +
            "id=" + id +
            ", name='" + name + '\'' +
            '}';
}
}

Below are the Annotations used while creating the entity classes –

Lombok annotations –

  • @Data – Define this class as Model class
  • @Builder – To build the model object at runtime ex. Create mock object for unit testing
  • @AllArgsConstructor – Create constructor with all arguments
  • @NoArgsConstructor – Default constructor

Spring Data JPA Annotations –

  • @Entity – This annotation marks the class annotations.
  • @Table – This annotation creates table in database.
  • @Id – It creates primary key in table.
  • @GeneratedValue – It defines primary key generation strategy like AUTO,IDENTITY,SEQUENCE etc.
  • @Column It defines column property for table.
  • @OneToOne – This annotation creates one to one relationship between Student and Address entities. The cascade property (CascadeType.ALL) defines what should happen with child table records when something happens with parent table records. On DELETE, UPDATE , INSERT operations in parent table child table should also be affected.
  • @JoinColumn – You can define column which creates foreign key in a table. In our example, ADDRESS_ID is a foreign key in STUDENT table which references to ID in ADDRESS table.

Step 3: Create the JPA repositories to query STUDENT and ADDRESS tables

StudentRepository and AddressRepository implemets JpaRepository which has methods to perform all CRUD operations. It has methods like save(), find(), delete(),exists(),count() to perform database operations.

package com.myjavablog.dao;

import com.myjavablog.model.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
public Student findByName(String name);
}

package com.myjavablog.dao;

import com.myjavablog.model.Address;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface AddressRepository extends JpaRepository<Address, Long>{
}

Step 4: Create the class BeanConfig to configure the bean for H2 database

This class creates a bean ServletRegistrationBean and autowires it to spring container. This bean actually required to access H2 database from console through browser.

package com.myjavablog;

import org.h2.server.web.WebServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfig {
@Bean
ServletRegistrationBean h2servletRegistration() {
    ServletRegistrationBean registrationBean = new ServletRegistrationBean(new WebServlet());
    registrationBean.addUrlMappings("/console/*");
    return registrationBean;
}
}

Step 5: Lat but not the least, You need to define application properties.

<h1>DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)</h1>
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
<h1>Hibernate</h1>
<h1>The SQL dialect makes Hibernate generate better SQL for the chosen database</h1>
spring.jpa.properties.hibernate.dialect =org.hibernate.dialect.H2Dialect
spring.datasource.driverClassName=org.h2.Driver
<h1>Hibernate ddl auto (create, create-drop, validate, update)</h1>
spring.jpa.hibernate.ddl-auto = update

logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE
server.port=8082
server.error.whitelabel.enabled=false

Step 6: Now run the application

Once you run the application records will be inserted to tables as below –

Spring Boot + Spring Data JPA + H2 Database

In this example , we will create a simple Spring boot application which will interact with the H2 database using Spring JPA library.

H2 database is an in memory database .For this tutorial , we will use H2 database for this demo so that we don’t need to perform heavy installation for other database like Oracle,MySQL.

GitHub Link

Tools –

  • Spring Boot
  • Spring JPA
  • H2 Database
  • IntelliJ IDEA editor
  • Maven
  • Lombok

Step 1: Create the simple spring boot web application in IntelliJ IDEA editor

Our final Project structure will look like below–

Step 2: Now define all maven dependencies required in this project

<?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">
<modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.myjavablog</groupId>
<artifactId>springhibernatewithh2database</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springhibernatewithh2database</name>
<description>Demo project for Spring Boot</description>
<pre><code><properties>
    <java.version>1.8</java.version>
</properties>

<dependencies>

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

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

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

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.apache.tomcat</groupId>
                <artifactId>tomcat-jdbc</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <!--<scope>runtime</scope>-->
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

</dependencies>

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

  • Lombok – We will be using lombok third party library to reduce boilerplate code for model/data objects, e.g., it can generate getters and setters for those object automatically by using Lombok annotations. The easiest way is to use the @Data annotation.
  • spring-boot-starter-data-jpa – This jar is used to connect to database .It also has a support to provide different JPA implementations to interact with the database like Hibernate, JPA Repository, CRUD Repository etc.
  • h2 – Its used to create H2 database when the spring boot application boots up. Spring boot will read the database configuration from application.properties file and creates a DataSource out of it.

Step 2: Create the Model class

package com.myjavablog.pojo;

import javax.persistence.*;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table
public class UserDetails {
<pre><code>@Id
@Column
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column
private String firstName;
@Column
private String lastName;
@Column
private String email;
@Column
private String password;</code></pre>
}

We have used Lombok library in Model class . You can see below annotation which are coming from Lambok jar –

  • @Data – Define this class as Model class
  • @Builder – To build the model object at runtime ex. Create mock object for unit testing
  • @AllArgsConstructor – Create constructor with all arguments
  • @NoArgsConstructor – Default constructor

So Lombok takes care of everything for you right from creating setters/ getters, Constructor , Build runtime objects and avoids boilerplate code .

Step 3: Configuration for the H2 database bean

package com.myjavablog.config;

import org.h2.server.web.WebServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfig {
<pre><code>@Bean
ServletRegistrationBean h2servletRegistration() {
    ServletRegistrationBean registrationBean = new ServletRegistrationBean(new WebServlet());
    registrationBean.addUrlMappings("/console/*");
    return registrationBean;
}</code></pre>
}

We can also configure the security for the application.

package com.myjavablog.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
<pre><code>@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity.csrf().disable().authorizeRequests().antMatchers("/").permitAll().and().authorizeRequests()
            .antMatchers("/console/**").permitAll()
            .antMatchers("/list/**").permitAll();
    httpSecurity.headers().frameOptions().disable();
}</code></pre>
}

Step 4: Service layer

package com.myjavablog.service;

import com.myjavablog.pojo.UserDetails;

import java.util.List;

public interface UserService {
public List getUserDetails();
}

package com.myjavablog.service;

import com.myjavablog.dao.UserDao;
import com.myjavablog.pojo.UserDetails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements UserService {
<pre><code>@Autowired
UserDao userDao;

@Override
public List getUserDetails() {

    return userDao.getUserDetails();
}
}

Step 5: DAO layer

package com.myjavablog.dao;

import com.myjavablog.pojo.UserDetails;

import java.util.List;

public interface UserDao {
<pre><code>public List getUserDetails();
}

package com.myjavablog.dao;

import com.myjavablog.pojo.UserDetails;

import javax.persistence.*;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.springframework.stereotype.Repository;
import java.util.List;

@Repository
public class UserDaoImpl implements UserDao {
@PersistenceContext
private EntityManager entityManager ;

@Override
public List getUserDetails() {
    Criteria criteria;
    criteria = entityManager.unwrap(Session.class).createCriteria(UserDetails.class);
    return criteria.list();
}
}

Step 7: Create Controller class

package com.myjavablog.controller;

import com.myjavablog.pojo.UserDetails;
import com.myjavablog.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.List;

@Controller
public class UserController {
@Autowired
private UserService userService;

@RequestMapping(value = "/list", method = RequestMethod.GET)
public ResponseEntity userDetails() {

    List userDetails = userService.getUserDetails();
    return new ResponseEntity(userDetails, HttpStatus.OK);
}
}

Step 8 : Create a properties file to configure Spring boot application and database

spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driverClassName=org.h2.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
server.port=8081
server.error.whitelabel.enabled=false

Step 9: Now application is ready . Run the application and Java application and access URL http://localhost:8081/console to access H2 database.

Once you connect to it you can insert records to table.

Now you can access the application to get the list of users.

Spring Boot + ActiveMQ

We will use Spring boot with ActiveMQ as below –

Github Link:  Download

We can connect to in memory or message queue hosted on external server –

Tools used for below project –

  1. Spring Boot 2.0.3.RELEASE
  2. Spring 5.0.7.RELEASE
  3. ActiveMQ Embeded 8
  4. Maven 3.3
  5. Java 8
  6. Spring Tool Suite IDE (STS)

Step 1: Project Structure

 

 

 

 

 

 

 

 

 

 

Step 2: Create a project named SpringBootMessageQueue in STS (Refer Create new project in STS). Additionally select JMS(ActiveMQ) dependency from starter project  dependencies popup –

Step 3: Below pom.xml will be generated for you by STS .

<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.anup.springboot</groupId>
<artifactId>Springboot_HelloWorld</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Springboot_HelloWorld Maven Webapp</name>
<url>http://maven.apache.org</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath />
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
</dependencies>

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

<finalName>Springboot_HelloWorld</finalName>
</build>
</project>

The spring-boot-starter-parent provides you all maven defaults required for any spring project.

Since we are developing a spring boot application , we also need to add spring-boot-starter-web dependency. Additionally we need to include spring-boot-starter-activemq for connecting to ActiveMQ.
Let’s do ActiveMQ configuration first.

Application Properties- 

Step 4: Update“Application.properties” file under /src/main/resources folder to create in memory MQ –

spring.activemq.in-memory=true
spring.activemq.pool.enabled=false

If you want to use activemq hosted on external server then you need to do configuration as below –

<span class="crayon-v">spring</span><span class="crayon-sy">.</span><span class="crayon-v">activemq</span><span class="crayon-sy">.</span><span class="crayon-v">broker</span><span class="crayon-o">-</span><span class="crayon-v">url</span><span class="crayon-o">=</span><span class="crayon-v">tcp</span><span class="crayon-o">:</span><span class="crayon-c">//localhost:61616</span>

Spring boot main file

Step 5:  “SpringBootApplicatioMain.java”  file must be created under com.myjavablog package by  STS

package com.anup.springboot;

import javax.jms.Queue;

import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.annotation.EnableJms;

@SpringBootApplication
@EnableJms
public class SpringBootApplicatioMain {

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

@Bean
public Queue queue() {
return new ActiveMQQueue("com.anup.testqueue");
}
}

This is the main file which bootstraps spring application.

We have just added @SpringBootApplication and it does all the work.
Let’s understand more about this annotation.
@SpringBootApplication is an annotation that adds all of the following:

@Configuration – It makes the class as a source of bean definitions for the application context.
@EnableAutoConfiguration – It enables Spring boot to add beans presents in classpath setting and various property setting.
Normally you would add @EnableWebMvc for a Spring MVC application, but Spring Boot adds it automatically when it sees spring-webmvc on the classpath.
This flags the application as a web application and activates key behaviors such as setting up a DispatcherServlet.
@ComponentScan – It tells Spring to look for other components, configurations, and services in the default package, allowing it to find the controllers.

@EnableJMS annotation is used to trigger search for method annotated with @JMSListener, hence to create JMS listener in the background.
If specific packages are not defined, scanning will occur from the package of the class that declares this annotation.

 

Step 6: Create a file named “WebSecurityConfiguaration.java” in package com.myjavablog

/**
*
*/
package com.myjavablog;

/**
* @author anupb
*
*/
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfiguaration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {

http.authorizeRequests().antMatchers("/hello*").access("hasRole('ROLE_ADMIN')").and().formLogin();

}

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(NoOpPasswordEncoder.getInstance()).
withUser("myjavablog").password("secure").roles("ADMIN");
}
}

@EnableWebSecurity – Enables security for our application.

http.authorizeRequests().antMatchers(“/hello*”) – Secures all the URLs containing hello word in it.

http.authorizeRequests().antMatchers(“/hello*”).access(“hasRole(‘ROLE_ADMIN’)”).and().formLogin() – Allows role based access to these URLs . User with only admin can access this URL.

auth.inMemoryAuthentication().withUser(“myjavablog”).password(“secure”).roles(“ADMIN”) – We are using in Memory authentication to authenticate the user. User credentials are stored in memory for this example. We can store them either in database , LDAP etc.

When user provides myjavablog/secure credentials in login form then only he can access URLs with /hello  as this user has ADMIN role.

 

Run the application

Step 10: Right Click on Project -> Debug As -> Maven Build

 

Step 8: Provide goals as below – 

mvn clean install spring-boot:run (Cmd prompt)

Or

 

Step 9:  Now once you run the application, spring boot will create a Queue in a memory and puts the messages onto that queue as below –

. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.3.RELEASE)

2018-06-24 21:14:27.007 INFO 17356 --- [ main] c.a.springboot.SpringBootApplicatioMain : Starting SpringBootApplicatioMain on DESKTOP-IK4A0TS with PID 17356 (started by anupb in E:\Study Material\Software Setups\UI\STS_Wksp\SpringBootMessageQueue)
2018-06-24 21:14:27.034 INFO 17356 --- [ main] c.a.springboot.SpringBootApplicatioMain : No active profile set, falling back to default profiles: default
2018-06-24 21:14:27.307 INFO 17356 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.spring[email protected]514646ef: startup date [Sun Jun 24 21:14:27 IST 2018]; root of context hierarchy
2018-06-24 21:14:29.976 INFO 17356 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2018-06-24 21:14:29.989 INFO 17356 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 2147483647
2018-06-24 21:14:30.127 WARN 17356 --- [ main] o.apache.activemq.broker.BrokerService : Memory Usage for the Broker (1024mb) is more than the maximum available for the JVM: 889 mb - resetting to 70% of maximum available: 622 mb
2018-06-24 21:14:30.422 INFO 17356 --- [ main] o.apache.activemq.broker.BrokerService : Using Persistence Adapter: MemoryPersistenceAdapter
2018-06-24 21:14:30.618 INFO 17356 --- [ JMX connector] o.a.a.broker.jmx.ManagementContext : JMX consoles can connect to service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi
2018-06-24 21:14:30.675 INFO 17356 --- [ main] o.apache.activemq.broker.BrokerService : Apache ActiveMQ 5.14.5 (localhost, ID:DESKTOP-IK4A0TS-57046-1529855070442-0:1) is starting
2018-06-24 21:14:30.687 INFO 17356 --- [ main] o.apache.activemq.broker.BrokerService : Apache ActiveMQ 5.14.5 (localhost, ID:DESKTOP-IK4A0TS-57046-1529855070442-0:1) started
2018-06-24 21:14:30.688 INFO 17356 --- [ main] o.apache.activemq.broker.BrokerService : For help or more information please see: http://activemq.apache.org
2018-06-24 21:14:30.819 INFO 17356 --- [ main] o.a.activemq.broker.TransportConnector : Connector vm://localhost started
Message has been put to queue by sender
2018-06-24 21:14:31.279 INFO 17356 --- [ main] c.a.springboot.SpringBootApplicatioMain : Started SpringBootApplicatioMain in 5.127 seconds (JVM running for 10.015)

 

 

 

 

 

 

 

 

Spring boot Data JPA+ Angular JS + MySQL Database CRUD

Github Link: 

We are using  Spring boot version 2.0.0.RELEASE . We will be creating simple TodoManager application using which we can manage our daily todo tasks. We will be using angular for front end. It will provide user interface from which you can add, update or delete tasks in todo list.We will use controller, JpaRepository classes to achieve these functionalities.We will connect to MySQL database using SessionFactory class of hibernate.

Tools used for below project –

  1. Spring Boot 2.0.0.RELEASE
  2. Spring 5.0.4.RELEASE
  3. Tomcat Embed 8
  4. Maven 3.3
  5. Java 8
  6. Spring Tool Suite IDE (STS)
  7. Spring Data JPA 2.0.5.RELEASE
  8. MySql 5.1.21

Step 1: Project Structure

Step 2: Create a project named TodoListManagerJPA in STS (Refer Create new project in STS)

Step 3: Change pom.xml as below –

<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.anup.springboot</groupId>
<artifactId>TodoListManagerJPA</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Springboot JPA Maven Webapp</name>
<url>http://maven.apache.org</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.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-data-jpa</artifactId>
</dependency>

<!-- JSTL for JSP -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>

<!-- For JSP compilation -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>

<!-- mySQL DB -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>

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

</dependencies>

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

<!-- <plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin> -->
</plugins>

<finalName>TodoListManagerJPA</finalName>
</build>
</project>

The spring-boot-starter-parent provides you all maven defaults required for any spring project. Since we are developing a web application, we also need to add spring-boot-starter-web dependency. Additionally we need to include spring-boot-starter-data-jpa to run this application with MySQL database.You need to also put mysql-connector-java for MySql JDBC driver.If you are using any other database, you need to use different database connector.
Let’s do hibernate configuration first.

Step 4: Create a  “application.properties”  file in package /src/main/resources

spring.mvc.view.prefix: /WEB-INF/views/
spring.mvc.view.suffix: .jsp
server.port=8081

## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url = jdbc:mysql://localhost:3306/test?useSSL=false
spring.datasource.username = root
spring.datasource.password = root

## Hibernate Properties

# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect

# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update

In the above properties file, the last two properties are for hibernate. Spring Boot uses Hibernate as the default JPA implementation.

The property spring.jpa.hibernate.ddl-auto is used for database initialization. I’ve used the value “update”for this property.

It does two things –

  • When you define a domain model, a table will automatically be created in the database and the fields of the domain model will be mapped to the corresponding columns in the table.
  • Any change to the domain model will also trigger an update to the table. For example, If you change the name or type of a field, or add another field to the model, then all these changes will be reflected in the mapped table as well.

Using update for spring.jpa.hibernate.ddl-auto property is fine for development. But, For production, You should keep the value of this property to “validate”, and use a database migration tool like Flyway for managing changes in the database schema.

Step 5: Create a “Task.java” model class in com.myjavablog.springboot.pojo package

package com.myjavablog.springboot.pojo;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
* @author anup
*
*/

@Entity
@Table(name="TASKS")
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(value = {"createdAt", "updatedAt"},
allowGetters = true)
public class Task implements Serializable {

/**
*
*/
private static final long serialVersionUID = 1L;

@Id
@Column(name="ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name="TASK_NAME")
private String taskName;

@Column(name="TASK_DESC")
private String taskDesc;

@Column(name="STATUS")
private String status;

@Column(nullable = false, updatable = false , name= "CREATED_AT")
@Temporal(TemporalType.TIMESTAMP)
@CreatedDate
private Date createdAt;

@Column(nullable = false, name= "UPDATED_AT")
@Temporal(TemporalType.TIMESTAMP)
@LastModifiedDate
private Date updatedAt;

public Long getId() {
return id;
}

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

public String getTaskName() {
return taskName;
}

public void setTaskName(String taskName) {
this.taskName = taskName;
}

public String getTaskDesc() {
return taskDesc;
}

public void setTaskDesc(String taskDesc) {
this.taskDesc = taskDesc;
}

public String getStatus() {
return status;
}

public void setStatus(String status) {
this.status = status;
}

public Date getCreatedAt() {
return createdAt;
}

public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}

public Date getUpdatedAt() {
return updatedAt;
}

public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
}

@Entity – This marks class as Entity

@Table – This maps class to database table

@Id – Marks the class variable as primary key column in table

@Column – Marks it as a column in table , we can also configure name attribute defining its name in database table

@Temporal – annotation is used with java.util.Dateand java.util.Calendar classes. It converts the date and time values from Java Object to compatible database type and vice versa.

@JsonIgnoreProperties – annotation is a Jackson annotation. Spring Boot uses Jackson for Serializing and Deserializing Java objects to and from JSON.This annotation is used because we don’t want the clients of the rest api to supply the createdAt and updatedAt values. If they supply these values then we’ll simply ignore them. However, we’ll include these values in the JSON response.

@EntityListeners(AuditingEntityListener.class)

In our Task model we have annotated createdAt and updatedAt fields with @CreatedDate and @LastModifiedDate annotations respectively.

Now, what we want is that these fields should automatically get populated whenever we create or update an entity.

To achieve this, we need to do two things –

  1. Add Spring Data JPA’s AuditingEntityListener to the domain model. We have already done this in our Task model with the annotation @EntityListeners(AuditingEntityListener.class).
  2. Enable JPA Auditing in the main application. Open TodoManagerApplication.java and add @EnableJpaAuditing annotation.

@GeneratedValue – Marking a field with the @GeneratedValue annotation specifies that a value will be automatically generated for that field. This is primarily intended for primary key fields .There are below types of strategies –

GenerationType.AUTO It is the default generation type and lets the persistence provider choose the generation strategy.

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", updatable = false, nullable = false)
private Long id;

GenerationType.IDENTITY – The GenerationType.IDENTITY is the easiest to use but not the best one from a performance point of view. It relies on an auto-incremented database column and lets the database generate a new value with each insert operation. From a database point of view, this is very efficient because the auto-increment columns are highly optimized, and it doesn’t require any additional statements.

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private Long id;

GenerationType.SEQUENCE – The GenerationType.SEQUENCE is my preferred way to generate primary key values and uses a database sequence to generate unique values.

If you don’t provide sequence name hibernate will provide its default sequence

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "id", updatable = false, nullable = false)
private Long id;

You can change that by referencing the name of a @SequenceGenerator in the generator attribute of the @GeneratedValue annotation. The @SequenceGenerator annotation lets you define the name of the generator, the name, and schema of the database sequence and the allocation size of the sequence.

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "book_generator")
@SequenceGenerator(name="book_generator", sequenceName = "book_seq", allocationSize=50)
@Column(name = "id", updatable = false, nullable = false)
private Long id;

GenerationType.TABLE – The GenerationType.TABLE gets only rarely used nowadays. It simulates a sequence by storing and updating its current value in a database table which requires the use of pessimistic locks which put all transactions into a sequential order. This slows down your application, and you should, therefore, prefer the GenerationType.SEQUENCE, if your database supports sequences, which most popular databases do

If you don’t provide sequence name hibernate will provide its default sequence

@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@Column(name = "id", updatable = false, nullable = false)
private Long id;

Summary:

  1. AUTO: Hibernate selects the generation strategy based on the used dialect,
  2. IDENTITY: Hibernate relies on an auto-incremented database column to generate the primary key,
  3. SEQUENCE: Hibernate requests the primary key value from a database sequence,
  4. TABLE: Hibernate uses a database table to simulate a sequence.

Step 6: Create database tables

create schema test;

create table TASKS (id bigint NOT NULL AUTO_INCREMENT, TASK_NAME varchar(255), TASK_DESC varchar(255), STATUS varchar(255) , CREATED_AT timestamp, UPDATED_AT timestamp, primary key (id));

INSERT INTO TASKS VALUES(1, 'Bath', 'Have a bath' , 'PENDING', SYSDATE, SYSDATE);

INSERT INTO TASKS VALUES(2, 'Snacks', 'Have snacks' , 'PENDING' , CURTIME() , CURTIME());

INSERT INTO TASKS VALUES(3, 'Office', 'Office' , 'PENDING' , CURTIME() , CURTIME());

INSERT INTO TASKS VALUES(4, 'Lunch', 'Lunch' , 'PENDING' , CURTIME() , CURTIME());

Controller class

Step 7: Create class “TodoController.java” in package com.myjavablog.springboot.controller

/**
*
*/
package com.myjavablog.springboot.controller;

import java.util.List;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.myjavablog.springboot.exception.ResourceNotFoundException;
import com.myjavablog.springboot.pojo.Task;
import com.myjavablog.springboot.repository.TodoRepository;

/**
* @author anup
*
*/

@RestController
public class TodoController {

@Autowired
TodoRepository todoRepository;

@PostMapping(value = "/todos/addTodo")
public Task addTodo(@Valid @RequestBody Task task) {
return todoRepository.save(task);
}

@PutMapping(value = "/todos/updateTodo")
public Task updateTodo(@Valid @RequestBody Task task) {

Task todo = todoRepository.findById(task.getId())
.orElseThrow(() -> new ResourceNotFoundException("Todo", "id", task.getId()));

todo.setStatus(task.getStatus());
todo.setTaskDesc(task.getTaskDesc());
todo.setTaskName(task.getTaskName());

Task updatedTask = todoRepository.save(todo);
return updatedTask;
}
@GetMapping(value = "/todos/getAllTodos")
public List<Task> getAllTodos() {
return todoRepository.findAll();
}

@DeleteMapping(value="/todos/deleteTodo/{id}")
public ResponseEntity<?> deleteCust(@PathVariable Long id) {
todoRepository.deleteById(id);

return ResponseEntity.ok().build();
}

}

@RestController annotation is a combination of Spring’s @Controller and @ResponseBody annotations.

Repository 

Step 8: Create interface “TodoRepository.java” in package “com.myjavablog.springboot.repository” and extend it from JpaRepository.

We have to create a repository to access Tasks from the database.

Well, Spring Data JPA comes to rescue us here. It comes with a JpaRepository interface which defines methods for all the CRUD operations on the entity, and a default implementation of JpaRepository called SimpleJpaRepository. JPA has eliminated lot of boilerplate code which we need to write for CRUD operations otherwise.

package com.myjavablog.springboot.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.myjavablog.springboot.pojo.Task;

/**
* @author anupb
*
*/
@Repository
public interface TodoRepository extends JpaRepository<Task, Long>{

}

we have annotated the interface with @Repository annotation. This tells Spring to bootstrap the repository during component scan.

Cool! That is all you have to do in the repository layer. You will now be able to use JpaRepository’s methods like save()findOne()findAll()count()delete() etc.

Custom Exception

Step 9: Create “ResourceNotFoundException.java” in “com.myjavablog.springboot.exception” package –

We have defined the Rest APIs for creating, retrieving, updating, and deleting a Task .

The APIs will throw a ResourceNotFoundException whenever a Task with a given id is not found in the database.

package com.myjavablog.springboot.exception;

import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.http.HttpStatus;
/**
* @author anupb
*
*/
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
private String resourceName;
private String fieldName;
private Object fieldValue;

public ResourceNotFoundException(String resourceName, String fieldName, Object fieldValue) {
super(String.format("%s not found with %s : '%s'", resourceName, fieldName, fieldValue));
this.resourceName = resourceName;
this.fieldName = fieldName;
this.fieldValue = fieldValue;
}

public String getResourceName() {
return resourceName;
}

public String getFieldName() {
return fieldName;
}

public Object getFieldValue() {
return fieldValue;
}
}

AngularJS UI Layer

Step 10: Create “index.jsp” under \src\main\webapp\WEB-INF\views\

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>

<html>
<head>
<link href="/css/app.css" rel="stylesheet"/>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js"></script>
<script type="text/javascript" src="/js/app.js"></script>

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Todo Manager</title>
</head>
<body ng-app="todoManager" ng-controller="todoController">
</br>
<h4 class="todo">Todo Manager</h4>

<form ng-submit="submitTodo()">
<table>

<tr>
<th colspan="2">Add/Edit todo</th>
</tr>
<tr>
<td>Task Name</td>
<td><input type="text" ng-model="todoForm.taskName" /></td>
</tr>
<tr>
<td>Task Desc</td>
<td><input type="text" ng-model="todoForm.taskDesc" /></td>
</tr>
<tr>
<td>Status</td>
<td><select id="status" ng-model="todoForm.status" ng-options="x for x in status" /></select></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Submit"
class="blue-button" /></td>
</tr>
</table>
</form>

<table>
<tr>

<th width="120">Task Name</th>
<th width="120">Task Desc</th>
<th width="60">Status</th>
<th width="60">Operations</th>

</tr>

<tr ng-repeat="todo in todos" ng-init="statusCls=getClass(todo)">

<td>{{ todo.taskName }}</td>
<td>{{ todo.taskDesc }}</td>
<td class="statusCls"> {{ todo.status }} </td>

<td><a ng-click="editTodo(todo)" class="blue-button">Edit</a>
| <a ng-click="deleteTodo(todo)" class="red-button">Delete</a></td>
</tr>

</table>

</body>
</html>

Step 11: Create javascript file “app.js” under \src\main\resources\static\js\

var app = angular.module("todoManager" , []);

app.controller("todoController" , function($scope, $http){

$scope.todos = [];
$scope.status = ["PENDING", "COMPLETED"];
$scope.todoForm = {
id : -1,
taskName : "",
taskDesc : ""
};

$scope.getClass = function(todo){

if(todo.status == 'PENDING')
return 'red';
else if(todo.status == 'COMPLETED'){
return 'green';
}
}

_refreshTodoData();

function _refreshTodoData(){

$http({
method : 'GET',
url : 'http://localhost:8082/todos/getAllTodos'
}).then(function successCallback(response) {
$scope.todos = response.data;

//alert($scope.todos);
}, function errorCallback(response) {
console.log(response.statusText);
});
}

$scope.submitTodo = function() {

var method = "";
var url = "";
if ($scope.todoForm.id == -1) {
//Id is absent in form data, it is create new todo operation
method = "POST";
url = '/todos/addTodo';
} else {
//Id is present in form data, it is edit todo operation
method = "PUT";
url = '/todos/updateTodo';
}

$http({
method : method,
url : url,
data : angular.toJson($scope.todoForm),
headers : {
'Content-Type' : 'application/json'
}
}).then( _success, _error );
};

$scope.deleteTodo = function(todo) {
$http({
method : 'DELETE',
url : '/todos/deleteTodo/' + todo.id
}).then(_success, _error);
};

$scope.editTodo = function(todo) {

$scope.todoForm.taskName = todo.taskName;
$scope.todoForm.taskDesc = todo.taskDesc;
$scope.todoForm.status = todo.status;
$scope.todoForm.id = todo.id;
};

function _success(response) {
//alert("success");
_refreshTodoData();
_clearFormData();
}

function _error(response) {
//alert("error");
console.log(response.statusText);
}

//Clear the form
function _clearFormData() {
$scope.todoForm.id = -1;
$scope.todoForm.taskName = "";
$scope.todoForm.taskDesc = "";
$scope.todoForm.status = "";

};
});

Step 12: Create CSS file “app.css” under \src\main\resources\static\css\ for adding style

.blue-button {
background: #25A6E1;
filter: progid: DXImageTransform.Microsoft.gradient( startColorstr='#25A6E1',
endColorstr='#188BC0', GradientType=0);
padding: 3px 5px;
color: #fff;
font-family: 'Helvetica Neue', sans-serif;
font-size: 12px;
border-radius: 2px;
-moz-border-radius: 2px;
-webkit-border-radius: 4px;
border: 1px solid #1A87B9;
cursor: pointer;
}

.red-button {
background: #CD5C5C;
padding: 3px 5px;
color: #fff;
font-family: 'Helvetica Neue', sans-serif;
font-size: 12px;
border-radius: 2px;
-moz-border-radius: 2px;
-webkit-border-radius: 4px;
border: 1px solid #CD5C5C;
cursor: pointer;
}

table {
font-family: "Helvetica Neue", Helvetica, sans-serif;
width: 50%;
}

caption {
text-align: left;
color: silver;
font-weight: bold;
text-transform: uppercase;
padding: 5px;
}

th {
background: SteelBlue;
color: white;
}

tbody tr:nth-child(even) {
background: WhiteSmoke;
}

tbody tr td:nth-child(2) {
text-align: center;
}

tbody tr td:nth-child(3), tbody tr td:nth-child(4) {
text-align: center;
font-family: monospace;
}

tfoot {
background: SeaGreen;
color: white;
text-align: right;
}

tfoot tr th:last-child {
font-family: monospace;
}

td, th {
border: 1px solid gray;
width: 25%;
text-align: left;
padding: 5px 10px;
}

#status{
width: 53%;
padding: 1px 0;
}

.todo {
font-size: 24px;
color: #CD5C5C;
text-transform: uppercase;
font-family: arial;
width: 50%;
background: #ccc;
text-align: center;
border-radius: 4px;
margin: 2% 0%;
padding: 3px 0;
box-shadow: 0px 1px 7px 1px grey;
}

.pending{
color: red;
}

.completed{
color: green;
}

  • $http – It’s used to make AJAX calls to server in order to submitTodo(), deleteTodo() , editTodo() task.
  • When you click on submit button on form, it actually calls POST or PUT depending on operation. If you click on edit and submit data then it will be PUT operation as it will update existing resource. If you directly submit data, then it will be POST operation to create new resource.
  • Every time you submit data, it calls _refreshTodoData() to refresh Todo table below.
  • When you call $http, you need to pass method type and URL, it will call it according, You can either put absolute URL or relative URL with respect to context root of web application.

Spring boot main file

Step 13: Create “TodoManagerApplication.java” a main spring file under com.anup.springboot

package com.myjavablog.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
@EnableJpaAuditing
@EnableJpaRepositories(basePackages="com.myjavablog.springboot.repository")
public class TodoManagerApplication {

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

This is the mail file which bootstraps spring application.

We have just added @SpringBootApplication and it does all the work.
Let’s understand more about this annotation.
@SpringBootApplication is an annotation that adds all of the following:

@Configuration – It makes the class as a source of bean definitions for the application context.
@EnableAutoConfiguration – It enables Spring boot to add beans presents in classpath setting and various property setting.
Normally you would add @EnableWebMvc for a Spring MVC application, but Spring Boot adds it automatically when it sees spring-webmvc on the classpath.
This flags the application as a web application and activates key behaviors such as setting up a DispatcherServlet.
@ComponentScan – It tells Spring to look for other components, configurations, and services in the default package, allowing it to find the controllers.
If specific packages are not defined, scanning will occur from the package of the class that declares this annotation.

Run the application

Step 14: Right Click on Project -> Debug As -> Maven Build

Step 15: Provide goals as below – 

mvn clean install spring-boot:run (Cmd prompt)

Or

Step 16: Now once the application is up and running, you can access it from below link –

Adding new task –

Editing the task –

Deleting the task –

Now we will try to update Task which is not present in database. It should throw a custom exception and we will get response as shown below –

Spring boot + Spring Security

We will use Spring boot with spring security as below –

Github Link:  Download

We can secure spring application using spring security API provided by spring –

Tools used for below project –

  1. Spring Boot 2.0.3.RELEASE
  2. Spring 5.0.7.RELEASE
  3. Tomcat Embed 8
  4. Maven 3.3
  5. Java 8
  6. Spring Tool Suite IDE (STS)

Step 1: Project Structure

This image has an empty alt attribute; its file name is sec_pjtstruc-291x300.jpg

Step 2: Create a project named SpringBootSpringSecurityDemo in STS (Refer Create new project in STS). Select web , security dependency from starter project  dependencies popup –

Step 3: Below pom.xml will be generated for you by STS . You need to add JSTL and Embeded tomcat dependency if it’s not present.

<?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">
<modelVersion>4.0.0</modelVersion>

<groupId>com.myjavablog</groupId>
<artifactId>SpringBootSpringSecurityDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>SpringBootSpringSecurityDemo</name>
<description>Demo project for Spring Boot with spring security</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

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

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

<!-- JSTL for JSP -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>

<!-- For JSP compilation -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/org.threeten/threetenbp -->
<dependency>
<groupId>org.threeten</groupId>
<artifactId>threetenbp</artifactId>
<version>0.7.2</version>
</dependency>
</dependencies>

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

</project>

The spring-boot-starter-parent provides you all maven defaults required for any spring project.

Since we are developing a web application, we also need to add spring-boot-starter-web dependency. Additionally we need to include spring-boot-starter-security to provide security to this web application.
Let’s do security configuration first.

Conroller class- 

Step 4: Create “HelloController .java” file under com.myjavablog.controller package –

package com.myjavablog.controller;

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

/**
* @author anupb
*
*/

@Controller
public class HelloController {

@GetMapping("/hello")
public String getHomePage(Model model) {

model.addAttribute("message", "Lets make our app secure");

return "hello";

}

}

Its a simple controller with  only hello method inside it.

Below are the annotations used-

@Controller  –   @Controller is used to mark classes as Spring MVC Controller.

@GetMapping – This anootation is used map GET requests from browser to java methods.

If you run the application at this stage , spring boot will bootstrap spring security and default security will be provided. If you run the application and try to access http://localhost:8081/hello . This request will be intercepted by Spring security and will be redirected to login page as below –

This image has an empty alt attribute; its file name is defaultLogin-300x181.jpg

Login with default username : user and password generated by spring in below logs –

This image has an empty alt attribute; its file name is springPwd-300x141.jpg

Spring boot main file to bootstrap application –

Step 5: Create a  “SpringBootSpringSecurityDemoApplication.java”  file in package com.myjavablog

package com.myjavablog;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootSpringSecurityDemoApplication {

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

This is the main file which bootstraps spring application.

We have just added @SpringBootApplication and it does all the work.
Let’s understand more about this annotation.
@SpringBootApplication is an annotation that adds all of the following:

@Configuration – It makes the class as a source of bean definitions for the application context.
@EnableAutoConfiguration – It enables Spring boot to add beans presents in classpath setting and various property setting.
Normally you would add @EnableWebMvc for a Spring MVC application, but Spring Boot adds it automatically when it sees spring-webmvc on the classpath.
This flags the application as a web application and activates key behaviors such as setting up a DispatcherServlet.
@ComponentScan – It tells Spring to look for other components, configurations, and services in the default package, allowing it to find the controllers.
If specific packages are not defined, scanning will occur from the package of the class that declares this annotation.

Step 6: Create a file named “WebSecurityConfiguaration.java” in package com.myjavablog

/**
*
*/
package com.myjavablog;

/**
* @author anupb
*
*/
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfiguaration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {

http.authorizeRequests().antMatchers("/hello*").access("hasRole('ROLE_ADMIN')").and().formLogin();

}

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(NoOpPasswordEncoder.getInstance()).
withUser("myjavablog").password("secure").roles("ADMIN");
}
}

@EnableWebSecurity – Enables security for our application.

http.authorizeRequests().antMatchers(“/hello*”) – Secures all the URLs containing hello word in it.

http.authorizeRequests().antMatchers(“/hello*”).access(“hasRole(‘ROLE_ADMIN’)”).and().formLogin() – Allows role based access to these URLs . User with only admin can access this URL.

auth.inMemoryAuthentication().withUser(“myjavablog”).password(“secure”).roles(“ADMIN”) – We are using in Memory authentication to authenticate the user. User credentials are stored in memory for this example. We can store them either in database , LDAP etc.

When user provides myjavablog/secure credentials in login form then only he can access URLs with /hello  as this user has ADMIN role.

Step 7: Now create application.properties file inside /src/main/resources folder.

spring.mvc.view.prefix: /WEB-INF/views/
spring.mvc.view.suffix: .jsp
server.port=8081

This is simillar to dispatcher servlet in spring MVC to configure view resolution.

Step 8: Create index.jsp inside webapp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HelloWorld</title>
</head>
<body>
<a href="hello.html">Click here to read hello message </a>
</br>
<a href="<c:url value="/logout" />">Logout</a>
</body>
</html>

Step 9: Create hello.jsp inside webapp/WEB-INF/views

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Hello world Page</title>
</head>
<body>
${message}
</body>
</html>

Run the application

Step 10: Right Click on Project -> Debug As -> Maven Build

Step 8: Provide goals as below – 

mvn clean install spring-boot:run (Cmd prompt)

Or

Step 9:  Now go to URL http://localhost:8082/. Index page will open up as below –

This image has an empty alt attribute; its file name is index-1-300x155.jpg

Once you click on the link, this request will be intercepted by spring security and you will be asked to enter username and password.

This image has an empty alt attribute; its file name is login-1-300x190.jpg

Home Page –

This image has an empty alt attribute; its file name is homepage-300x130.jpg

Restful webservices using Spring boot

Github Link:  Download

We are using  Spring boot version 1.5.9.RELEASE . We will be creating simple Todo Manager application which provides endpoints to expose todo tasks data without using any database.

Spring boot makes it very easy to develop REST API . We don’t need to worry for JSON conversion using jacksondatabind jar as earlier. Spring boot provides JSON dependency by default for us.

Tools used for below project –

  1. Spring Boot 2.0.2.RELEASE
  2. Spring 5.0.6.RELEASE
  3. Tomcat Embed 8
  4. Maven 3.3
  5. Java 8
  6. Spring Tool Suite IDE (STS)

Step 1: Project Structure

 

 

 

 

 

 

 

 

Step 2: Create a project named SpringBootRestful in STS (Refer Create new project in STS)

Step 3: Change pom.xml as below –

<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.anup.springboot</groupId>
<artifactId>TodoListManager</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>TodoListManager Maven Webapp</name>
<url>http://maven.apache.org</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</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-data-jpa</artifactId>
</dependency>

<!-- JSTL for JSP -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>

<!-- For JSP compilation -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.threeten/threetenbp -->
<dependency>
<groupId>org.threeten</groupId>
<artifactId>threetenbp</artifactId>
<version>0.7.2</version>
</dependency>

<!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope> </dependency> -->
<!-- H2 Database
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>-->

<!-- mySQL DB -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>

</dependencies>

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

</plugins>

<finalName>TodoListManager</finalName>
</build>
</project>

The spring-boot-starter-parent provides you all maven defaults required for any spring project. Since we are developing a web application, we also need to add spring-boot-starter-web dependency. Additionally we need to include spring-boot-starter-data-jpa to run this application with hibernate.You need to also put mysql-connector-java for MySql JDBC driver.If you are using any other database, you need to use different database connector.
Let’s do hibernate configuration first.

Model class –

Step 4: Create a “Todo.java” model class in com.anup.springboot.pojo package

package com.anup.springboot.pojo;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

/**
* @author anup
*
*/

@Entity
@Table(name = "TODO")
public class Todo implements Serializable {

public Todo() {
super();
}

public Todo(Long id, String taskName, String taskDesc, String status) {
super();
this.id = id;
this.taskName = taskName;
this.taskDesc = taskDesc;
this.status = status;
}

@Id
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "TASK_NAME")
private String taskName;

@Column(name = "TASK_DESC")
private String taskDesc;

@Column(name = "STATUS")
private String status;

public Long getId() {
return id;
}

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

public String getTaskName() {
return taskName;
}

public void setTaskName(String taskName) {
this.taskName = taskName;
}

public String getTaskDesc() {
return taskDesc;
}

public void setTaskDesc(String taskDesc) {
this.taskDesc = taskDesc;
}

public String getStatus() {
return status;
}

public void setStatus(String status) {
this.status = status;
}

}

@Entity – This marks class as Entity

@Table – This maps class to database table

@Id – Marks the class variable as primary key column in table

@Column – Marks it as a column in table , we can also configure name attribute defining its name in database table

@GeneratedValue – Marking a field with the @GeneratedValue annotation specifies that a value will be automatically generated for that field. This is primarily intended for primary key fields .There are below types of strategies –

GenerationType.AUTO It is the default generation type and lets the persistence provider choose the generation strategy.

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", updatable = false, nullable = false)
private Long id;

GenerationType.IDENTITY – The GenerationType.IDENTITY is the easiest to use but not the best one from a performance point of view. It relies on an auto-incremented database column and lets the database generate a new value with each insert operation. From a database point of view, this is very efficient because the auto-increment columns are highly optimized, and it doesn’t require any additional statements.

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private Long id;

GenerationType.SEQUENCE – The GenerationType.SEQUENCE is my preferred way to generate primary key values and uses a database sequence to generate unique values.

If you don’t provide sequence name hibernate will provide its default sequence

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "id", updatable = false, nullable = false)
private Long id;

You can change that by referencing the name of a @SequenceGenerator in the generator attribute of the @GeneratedValue annotation. The @SequenceGenerator annotation lets you define the name of the generator, the name, and schema of the database sequence and the allocation size of the sequence.

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "book_generator")
@SequenceGenerator(name="book_generator", sequenceName = "book_seq", allocationSize=50)
@Column(name = "id", updatable = false, nullable = false)
private Long id;

GenerationType.TABLE – The GenerationType.TABLE gets only rarely used nowadays. It simulates a sequence by storing and updating its current value in a database table which requires the use of pessimistic locks which put all transactions into a sequential order. This slows down your application, and you should, therefore, prefer the GenerationType.SEQUENCE, if your database supports sequences, which most popular databases do

If you don’t provide sequence name hibernate will provide its default sequence

@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@Column(name = "id", updatable = false, nullable = false)
private Long id;

Summary:

  1. AUTO: Hibernate selects the generation strategy based on the used dialect,
  2. IDENTITY: Hibernate relies on an auto-incremented database column to generate the primary key,
  3. SEQUENCE: Hibernate requests the primary key value from a database sequence,
  4. TABLE: Hibernate uses a database table to simulate a sequence.

Conroller class- 

Step 5: Create “TodoController .java” file under com.myjavablog.controller package –

/**
*
*/
package com.myjavablog.controller;

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

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.myjavablog.model.Task;

/**
* @author anupb
*
*/
@RestController
public class TodoController {

static List<Task> taskList = new ArrayList<Task>();
static {
Task t1 = new Task(1l, "Walking", "Walking at 6 AM", "PENDING");
Task t2 = new Task(2l, "Breakfast", "Breakfast 7 AM", "COMPLETED");
Task t3 = new Task(3l, "Office", "Office at 9 AM", "COMPLETED");
Task t4 = new Task(4l, "Lunch", "Lunch at 1 PM", "PENDING");
Task t5 = new Task(5l, "Snacks", "Snacks at 6 PM", "PENDING");

taskList.add(t1);
taskList.add(t2);
taskList.add(t3);
taskList.add(t4);
taskList.add(t5);
}

@RequestMapping(value = "/tasks", method = RequestMethod.GET, headers = "Accept=application/json")
public List<Task> getTasks() {

return taskList;
}

@RequestMapping(value = "/addTask", method = RequestMethod.POST, headers = "Accept=application/json")
public String addTask(@RequestBody Task task) {

taskList.add(task);

return "Task added Succesfully!!!";
}

@RequestMapping(value = "/task/{taskId}", method = RequestMethod.GET, headers = "Accept=application/json")
public Task getTask(@PathVariable Long taskId) {

for (Task task : taskList) {

if (task.getId() == taskId)
return task;
}
return null;
}

@RequestMapping(value = "/deleteTask/{taskId}", method = RequestMethod.DELETE, headers = "Accept=application/json")
public String deleteTask(@PathVariable Long taskId) {

boolean flag = false;
Task tempTask = null;
for (Task task : taskList) {

if (task.getId() == taskId) {
tempTask = task;
break;
}
}

flag = taskList.remove(tempTask);
if (flag)
return "Task deleted successfully!!!!!";
else
return "Error in deleting Task!!!!!";
}

@RequestMapping(value = "/updateTask/{id}/{status}", method = RequestMethod.PUT, headers = "Accept=application/json")
public String updateTask(@PathVariable Long id, @PathVariable String status) {

for (Task task : taskList) {

if (task.getId() == id) {
task.setStatus(status);
}
}

return "Task updated Succesfully!!!";
}
}

 Below are the annotations used-

@RestController  –   This is a convenience annotation that does nothing more than adding                          the @Controller and @ResponseBody annotations.  (Note – @Controller is used to mark classes as Spring MVC Controller.)

@PathVariable –  This annotation is used to obtain some placeholder from the URI. Placeholders are generally of primitive datatype.

@RequestBody – This annotation is used to obtain some placeholder from the URI. Placeholders are generally of class objects in JSON format.

@RequestMapping – This anootation is used map requests from URI to java methods.

Spring boot main file

Step 6: Create a  “SpringBootRestfulApplication.java”  file in package com.myjavablog

package com.myjavablog;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootRestfulApplication {

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

This is the mail file which bootstraps spring application.

We have just added @SpringBootApplication and it does all the work.
Let’s understand more about this annotation.
@SpringBootApplication is an annotation that adds all of the following:

@Configuration – It makes the class as a source of bean definitions for the application context.
@EnableAutoConfiguration – It enables Spring boot to add beans presents in classpath setting and various property setting.
Normally you would add @EnableWebMvc for a Spring MVC application, but Spring Boot adds it automatically when it sees spring-webmvc on the classpath.
This flags the application as a web application and activates key behaviors such as setting up a DispatcherServlet.
@ComponentScan – It tells Spring to look for other components, configurations, and services in the default package, allowing it to find the controllers.
If specific packages are not defined, scanning will occur from the package of the class that declares this annotation.

Run the application

Step 7: Right Click on Project -> Debug As -> Maven Build

 

Step 8: Provide goals as below – 

mvn clean install spring-boot:run (Cmd prompt)

Or

Step 9: Now once the application is up and running, you can access it from POSTMAN tool as below –

Get all tasks –

 

 

 

 

 

 

 

 

 

 

Get single task –

 

 

 

 

 

 

 

 

Add task –

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Delete task –

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Update Task –

Before

 

 

 

 

 

 

 

 

 

After  –

 

 

 

 

 

 

 

Bitnami