Saturday 25 August 2018

Unit Testing of REST Service using JUnit and Spring Boot

Junit for REST Web Service using Spring Boot

We can use https://start.spring.io to create this project and we can add following dependency.

Dependency needed for this project:
  • Web
  • MySQL
  • JPA
  • Test
  • Spring-boot-maven-plugin
We will create Unit Test for the CustomerController which is a REST Controller. To mock, the controller services we will use Mockito. For doing the unit Test for REST service, we can use

@WebMvcTest which is used for testing Spring MVC application. For this test, we will focus on testing the Controller class.

@RunWith(SpringRunner.class) : SpringRunner is a form of SpringJUnit4ClassRunner which extends BlockJUnit4ClassRunner and provides the functionality to launch a Spring Test Context Framework.

@Autowired private MockMvc mockMvc : MockMvc is main entrance for server-side Spring MVC test support. It helps us to execute requests against the test context.

@MockBean private CustomerService customerService: MockBean is used to add mocks to a Spring ApplicationContext. A mock of customerService is created and auto-wired into the CustomerController.

JSONAssert.assertEquals(): We can use org.skyscreamer.jsonassert.JSONAssert which allows us to do partial asserts against a String of JSON type. We can pass strict as false since we do not want to check for all fields in the response.



1. pom.xml

<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.gaurav</groupId>
<artifactId>JunitWithSpringBoot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>

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

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>JunitWithSpringBoot</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

2. Customer.java

package com.gaurav.spring.bean;

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

@Entity
@Table(name = "Customer")
public class Customer {


public Customer(){
}

public Customer(int id, String firstName, String lastName, String gender, int age) {
super();
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.age = age;
}

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;

@Column(name = "first_name")
private String firstName;

@Column(name = "last_name")
private String lastName;

@Column(name = "gender")
private String gender;

@Column(name = "age")
private int age;

public int getId() {
return id;
}

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

public String getFirstName() {
return firstName;
}

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

public String getLastName() {
return lastName;
}

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

public String getGender() {
return gender;
}

public void setGender(String gender) {
this.gender = gender;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Customer other = (Customer) obj;
if (id != other.id)
return false;
return true;
}


}

3. CustomerDao.java

package com.gaurav.spring.dao;

import java.util.List;

import com.gaurav.spring.bean.Customer;

public interface CustomerDao {
public Integer addCustomer(Customer customer);
public List<Customer> getCustomer();
public Customer findById(int id);
public Customer update(Customer customer, int id);
public boolean delete(int id);
}

4. CustomerDaoImpl.java

package com.gaurav.spring.dao;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Repository;
import com.gaurav.spring.bean.Customer;

@Repository
public class CustomerDaoImpl implements CustomerDao {
@Autowired
private SessionFactory sessionFactory;

public Integer addCustomer(Customer customer) {
Session session = sessionFactory.getCurrentSession();
Integer id = (Integer)session.save(customer);
System.out.println("Generated Identifier is:"+id);
System.out.println("after customer : customer id's = "+customer.getId());
return id;
}

@SuppressWarnings("unchecked")
public List<Customer> getCustomer() {
Session session = sessionFactory.getCurrentSession();
List<Customer> list = session.createCriteria(Customer.class).list();
return list;
}

public Customer findById(int id) {
Session session = sessionFactory.getCurrentSession();
Customer customer = (Customer) session.get(Customer.class, id);
return customer;
}

public Customer update(Customer customerObj, int id) {
Session session = sessionFactory.getCurrentSession();
Customer customer = (Customer) session.get(Customer.class, id);
customer.setFirstName(customerObj.getFirstName());
customer.setLastName(customerObj.getLastName());
customer.setGender(customerObj.getGender());
customer.setAge(customerObj.getAge());
session.update(customer);
return customer;
}

public boolean delete(int id) {
boolean isExistsAndDeleted = false;
Session session = sessionFactory.getCurrentSession();
Customer customer = findById(id);
if (customer != null) {
session.delete(customer);
isExistsAndDeleted = true;
}
return isExistsAndDeleted;
}
}

5. CustomerService.java

package com.gaurav.spring.service;

import java.util.List;

import com.gaurav.spring.bean.Customer;

public interface CustomerService {
public Integer createCustomer(Customer customer);
public List<Customer> getCustomer();
public Customer findById(int id);
public Customer update(Customer customer, int id);
public boolean deleteCustomerById(int id);
}

/** Transaction Management */

6. CustomerServiceImpl.java

package com.gaurav.spring.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.gaurav.spring.bean.Customer;
import com.gaurav.spring.dao.CustomerDao;

@Service
@Transactional
public class CustomerServiceImpl implements CustomerService {

@Autowired
CustomerDao customerDao;

@Transactional(propagation=Propagation.SUPPORTS)
public List<Customer> getCustomer() {
return customerDao.getCustomer();
}

@Transactional(propagation=Propagation.SUPPORTS)
public Customer findById(int id) {
return customerDao.findById(id);
}
@Transactional(propagation=Propagation.REQUIRES_NEW)
public Integer createCustomer(Customer customer) {
Integer custId = customerDao.addCustomer(customer);
return custId;
}

@Transactional(propagation=Propagation.REQUIRES_NEW)
public boolean deleteCustomerById(int id) {
boolean isDeleted = customerDao.delete(id);
return isDeleted;
}
@Transactional(propagation=Propagation.REQUIRED)
public Customer update(Customer customer, int id) {
return customerDao.update(customer, id);
}
}

7. CustomerController.java

package com.gaurav.spring.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;

import com.gaurav.spring.bean.Customer;
import com.gaurav.spring.service.CustomerService;

@RestController
@RequestMapping(value = { "/customer" })
public class CustomerController {
@Autowired
CustomerService customerService;

@GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Customer> getCustomerById(@PathVariable("id") int id) {
System.out.println("Fetching customer with id " + id);
Customer customer = customerService.findById(id);
if (customer == null) {
return new ResponseEntity<Customer>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<Customer>(customer, HttpStatus.OK);
}

@PostMapping(value = "/create", headers = "Accept=application/json")
public ResponseEntity<Void> createCustomer(@RequestBody Customer customer, UriComponentsBuilder ucBuilder) {
customerService.createCustomer(customer);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/customer/{id}").buildAndExpand(customer.getId()).toUri());
return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}

@GetMapping(value = "/get", headers = "Accept=application/json")
public List<Customer> getAllCustomer() {
List<Customer> customers = customerService.getCustomer();
return customers;

}

@PutMapping(value = "/update", headers = "Accept=application/json")
public ResponseEntity<String> updateCustomer(@RequestBody Customer currentCustomer) {
Customer customer = customerService.findById(currentCustomer.getId());
if (customer == null) {
return new ResponseEntity<String>(HttpStatus.NOT_FOUND);
}
customerService.update(currentCustomer, currentCustomer.getId());
return new ResponseEntity<String>(HttpStatus.OK);
}

@DeleteMapping(value = "/{id}", headers = "Accept=application/json")
public ResponseEntity<Customer> deleteCustomer(@PathVariable("id") int id) {
Customer customer = customerService.findById(id);
if (customer == null) {
return new ResponseEntity<Customer>(HttpStatus.NOT_FOUND);
}
customerService.deleteCustomerById(id);
return new ResponseEntity<Customer>(HttpStatus.NO_CONTENT);
}

}

8. HibernateConfiguration.java

package com.gaurav.spring.configuration;

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
public class HibernateConfiguration {

@Value("${spring.datasource.driver}")
private String DB_DRIVER;

@Value("${spring.datasource.url}")
private String DB_URL;

@Value("${spring.datasource.username}")
private String DB_USERNAME;

@Value("${spring.datasource.password}")
private String DB_PASSWORD;

@Value("${spring.jpa.hibernate.dialect}")
private String HIBERNATE_DIALECT;

@Value("${spring.jpa.show-sql}")
private String HIBERNATE_SHOW_SQL;

@Value("${spring.jpa.hibernate.ddl-auto}")
private String HIBERNATE_HBM2DDL_AUTO;

@Value("${spring.jpa.entitymanager.packagesToScan}")
private String ENTITYMANAGER_PACKAGES_TO_SCAN;

@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(DB_DRIVER);
dataSource.setUrl(DB_URL);
dataSource.setUsername(DB_USERNAME);
dataSource.setPassword(DB_PASSWORD);
return dataSource;
}

@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(ENTITYMANAGER_PACKAGES_TO_SCAN);
Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.dialect", HIBERNATE_DIALECT);
hibernateProperties.put("hibernate.show_sql", HIBERNATE_SHOW_SQL);
hibernateProperties.put("hibernate.hbm2ddl.auto", HIBERNATE_HBM2DDL_AUTO);
sessionFactory.setHibernateProperties(hibernateProperties);
return sessionFactory;
}

@Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory().getObject());
return txManager;
}

}

9. SpringbootWithJUnit.java

package com.gaurav;

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

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

}

10. application.properties

logging.level.org.springframework.web=INFO
spring.datasource.driver: com.mysql.jdbc.Driver
spring.datasource.url: jdbc:mysql://localhost:3306/experimentdemo
spring.datasource.username:root
spring.datasource.password:root

spring.jpa.hibernate.dialect:org.hibernate.dialect.MySQL5Dialect
spring.jpa.show-sql:true
spring.jpa.hibernate.ddl-auto :update
spring.jpa.entitymanager.packagesToScan:com.gaurav

11. CustomerControllerTest.java

package com.gaurav.spring.controller;

import static org.junit.Assert.assertEquals;

import java.util.Arrays;
import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.skyscreamer.jsonassert.JSONAssert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import com.gaurav.spring.bean.Customer;
import com.gaurav.spring.service.CustomerService;

@RunWith(SpringRunner.class)
@WebMvcTest(value = CustomerController.class)
public class CustomerControllerTest {
@Autowired
private MockMvc mockMvc;

@MockBean
CustomerService customerService;
Customer mockCustomer = new Customer(3, "Kumar","Gaurav", "Male", 34);
List<Customer> mockCustomerList = Arrays.asList(new Customer(3, "Kumar","Gaurav", "Male", 34), new Customer(4, "Aditi","Kumari", "Female", 25));
String customerJson = "{\"id\": 2,\"firstName\": \"Maya\",\"lastName\": \"Sree\",\"gender\": \"Female\",\"age\": 35}";
/*
* We can use this block to initialize the Mockito
* @Before
    public void init(){
        MockitoAnnotations.initMocks(this);
        mockMvc = MockMvcBuilders
                .standaloneSetup(customerController)
                .build();
    }*/
@Test
public void getCustomerById() throws Exception {
Mockito.when(
customerService.findById(Mockito.anyInt())).thenReturn(mockCustomer);
RequestBuilder requestBuilder = MockMvcRequestBuilders.get(
"/customer/3").accept(
MediaType.APPLICATION_JSON);

MvcResult result = mockMvc.perform(requestBuilder).andReturn();

System.out.println(result.getResponse());
String expected = "{id:3,firstName:Kumar,lastName:Gaurav, gender:Male, age:34}";

JSONAssert.assertEquals(expected, result.getResponse()
.getContentAsString(), false);
}
@Test
public void getAllCustomer() throws Exception {

Mockito.when(customerService.getCustomer()).thenReturn(mockCustomerList);

RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/customer/get").accept(MediaType.APPLICATION_JSON);

MvcResult result = mockMvc.perform(requestBuilder).andReturn();

System.out.println(result.getResponse());

String expectedList = "[{\"id\":3,\"firstName\":\"Kumar\",\"lastName\":\"Gaurav\",\"gender\":\"Male\",\"age\":34},{\"id\":4,\"firstName\":\"Aditi\",\"lastName\":\"Kumari\",\"gender\":\"Female\",\"age\":25}]";

JSONAssert.assertEquals(expectedList, result.getResponse().getContentAsString(), false);

}

@Test
public void createCustomer() throws Exception{
Integer generatedId = 5;
Mockito.when(customerService.createCustomer(Mockito.anyObject())).thenReturn(generatedId);
Mockito.when(
customerService.createCustomer(Mockito.any(Customer.class))).thenReturn(mockCustomer.getId());

RequestBuilder requestBuilder = MockMvcRequestBuilders
.post("/customer/create")
.accept(MediaType.APPLICATION_JSON).content(customerJson)
.contentType(MediaType.APPLICATION_JSON);

MvcResult result = mockMvc.perform(requestBuilder).andReturn();

MockHttpServletResponse response = result.getResponse();

assertEquals(HttpStatus.CREATED.value(), response.getStatus());

assertEquals("http://localhost/customer/2",
response.getHeader(HttpHeaders.LOCATION));
}

@Test
public void updateCustomer() throws Exception{
Customer customer = new Customer(3, "Kumar","Gaurav", "Male", 34);
String customerStr3 = "{\"id\": 3,\"firstName\": \"Kumar\",\"lastName\": \"Gaurav\",\"gender\": \"Male\",\"age\": 34}";
Mockito.when(customerService.findById(customer.getId())).thenReturn(customer);
Mockito.when(customerService.update(customer, customer.getId())).thenReturn(customer);
RequestBuilder requestBuilder = MockMvcRequestBuilders
.put("/customer/update")
.accept(MediaType.APPLICATION_JSON).content(customerStr3)
.contentType(MediaType.APPLICATION_JSON);

MvcResult result = mockMvc.perform(requestBuilder).andReturn();

MockHttpServletResponse response = result.getResponse();
assertEquals(200, response.getStatus());
Mockito.verify(customerService, Mockito.times(1)).findById(customer.getId());
Mockito.verify(customerService, Mockito.times(1)).update(customer, customer.getId());
Mockito.verifyZeroInteractions(customerService);
}

@SuppressWarnings("unused")
@Test
public void deleteCustomer() throws Exception{
Customer customer = new Customer(3, "Kumar","Gaurav", "Male", 34);
String customerStr3 = "{\"id\": 3,\"firstName\": \"Kumar\",\"lastName\": \"Gaurav\",\"gender\": \"Male\",\"age\": 34}";
Mockito.when(customerService.findById(customer.getId())).thenReturn(customer);
Mockito.when(customerService.deleteCustomerById(customer.getId())).thenReturn(true);
RequestBuilder requestBuilder = MockMvcRequestBuilders
.delete("/customer/3")
.accept(MediaType.APPLICATION_JSON).content(customerStr3)
.contentType(MediaType.APPLICATION_JSON);

MvcResult result = mockMvc.perform(requestBuilder).andReturn();

Mockito.verify(customerService, Mockito.times(1)).findById(customer.getId());
Mockito.verify(customerService, Mockito.times(1)).deleteCustomerById(customer.getId());
Mockito.verifyNoMoreInteractions(customerService);
}

}

URL's to test using POSTMAN or REST Client

1. POST:- http://localhost:8080/customer/create
{
    "gender": "Female",
    "firstName": "Simran",
    "lastName": "Diva",
    "age": 16
}

2. GET:- http://localhost:8080/customer/get

3. GET:- http://localhost:8080/customer/1

4. PUT:- http://localhost:8080/customer/update
{
    "id":6,
    "gender": "Female",
    "firstName": "Sanjay",
    "lastName": "Kumar",
    "age": 19
}

5. DELETE:- http://localhost:8080/customer/6

Saturday 18 August 2018

Spring Boot & Hibernate With Spring Data JPA(Traditional Approach)

Spring Data-JPA With Hibernate



As we know that, JPA is a specification whereas Hibernate is a specific implementation of that specification. If we are using Hibernate it means we are tightly coupling our code with specific providers which restricts us to freely move towards different approach or implementation if required in future.

Spring Data JPA adds a layer of abstraction means it defines a standard or generic design to support persistence layer in Spring context. So, Spring Data JPA provides a definition to implement repositories that are referenced by JPA specification using the provider which we mention. Spring-data-JPA is the spring way to access data using JPA. We could use spring-data-rest on top of spring-data-JPA to create a REST-API layer with no code on top of your repositories and entities.



We will see below an example of hibernate with traditional approach using spring boot.

Use https://start.spring.io/  to create spring boot project with adding web and Spring-data-JPA dependency. I have also added mysql connector dependency.


1) pom.xml

<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.gaurav</groupId>
<artifactId>springboot-hibernate-Spring-Data-JPA</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>

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

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>

</project>

2) Employee.java

package com.gaurav.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
/**
 * @author Gaurav
 */
@Entity
@Table(name="employee")
public class Employee {

@Id
@Column
@GeneratedValue
private int id;

@Column
private String firstName;
@Column
private String lastName;
@Column
private String email;
@Column
private String designation;

public int getId() {
return id;
}

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

public String getFirstName() {
return firstName;
}

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

public String getLastName() {
return lastName;
}

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

public String getEmail() {
return email;
}

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

public String getDesignation() {
return designation;
}

public void setDesignation(String designation) {
this.designation = designation;
}
}


3. EmployeeDao.java

package com.gaurav.dao;

import java.util.List;

import com.gaurav.model.Employee;
/**
 * @author Gaurav
 */
public interface EmployeeDao {
public List<Employee> getAllEmployeeDetails();
public Employee getEmployeeById(int id);
public int saveEmployee(Employee emp);

}

4. EmployeeDaoImpl.java

package com.gaurav.dao.impl;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.gaurav.dao.EmployeeDao;
import com.gaurav.model.Employee;
/**
 * @author Gaurav
 */
@Repository
public class EmployeeDaoImpl implements EmployeeDao {

@Autowired
private SessionFactory sessionFactory;
@SuppressWarnings("unchecked")
public List<Employee> getAllEmployeeDetails() {
Criteria criteria = sessionFactory.openSession().createCriteria(Employee.class);
return criteria.list();
}
@SuppressWarnings("unchecked")
public Employee getEmployeeById(int id){
Employee employee = null;
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(Employee.class);
List<Employee> employeeList = criteria.add(Restrictions.eq("id", new Integer(id))).list();
if(!employeeList.isEmpty())
employee = employeeList.get(0);
tx.commit();
session.close();
return employee;
}
public int saveEmployee(Employee emp){
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Integer i = (Integer)session.save(emp);
System.out.println("Generated Identifier while saving the employee object:"+ i);
tx.commit();
session.close();
return i;
}
}

5. EmployeeService.java

package com.gaurav.service;

import java.util.List;

import com.gaurav.model.Employee;
/**
 * @author Gaurav
 */
public interface EmployeeService {

List<Employee> getAllEmployeeDetails();
public Employee getEmpById(int id);
public int saveEmployee(Employee emp);

}

6. EmployeeServiceImpl.java

package com.gaurav.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.gaurav.dao.EmployeeDao;
import com.gaurav.model.Employee;
import com.gaurav.service.EmployeeService;
/**
 * @author Gaurav
 */
@Service
public class EmployeeServiceImpl implements EmployeeService {

@Autowired
private EmployeeDao employeeDao;

public List<Employee> getAllEmployeeDetails() {
return employeeDao.getAllEmployeeDetails();

}

public Employee getEmpById(int id){
return employeeDao.getEmployeeById(id);
}

public int saveEmployee(Employee emp){
return employeeDao.saveEmployee(emp);
}
}

7. EmployeeController.java

package com.gaurav.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.gaurav.model.Employee;
import com.gaurav.service.EmployeeService;

@RestController
@RequestMapping("/rest")
public class EmployeeController {
@Autowired
private EmployeeService empService;
@RequestMapping(value = "/allemps", method = RequestMethod.GET)
public ResponseEntity<List<Employee>> allEmployeeDetails() {
        
List<Employee> empDetails = empService.getAllEmployeeDetails();
return new ResponseEntity<List<Employee>>(empDetails, HttpStatus.OK);
}
@GetMapping(value = "/emp/{id}")
public ResponseEntity<Employee> getEmployeeById(@PathVariable int id){
Employee employee = empService.getEmpById(id);
return new ResponseEntity<Employee>(employee, HttpStatus.OK);
}
@PostMapping(value = "/save")
public ResponseEntity<Integer> saveEmployee(@RequestBody Employee emp){
Integer id = empService.saveEmployee(emp);
return new ResponseEntity<Integer>(id, HttpStatus.OK);
}
}

8. SpringBootHibernateDemo.java

package com.gaurav;

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

@SpringBootApplication
public class SpringBootHibernateDemo {

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

}

9. application.properties

server.port=8989
spring.datasource.url = jdbc:mysql://localhost:3306/experiment
spring.datasource.username = root
spring.datasource.password = root

spring.jpa.show-sql = true

spring.jpa.hibernate.ddl-auto = update

spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect

10. HibernateBeanConfiguration.java

package com.gaurav.hibernate.util;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.persistence.EntityManagerFactory;


@Configuration
public class HibernateBeanConfiguration {

@Autowired
private EntityManagerFactory entityManagerFactory;

@Bean
public SessionFactory getSessionFactory() {
    if (entityManagerFactory.unwrap(SessionFactory.class) == null) {
        throw new NullPointerException("Session factory is not available");
    }
    return entityManagerFactory.unwrap(SessionFactory.class);
}

}


Result:

When executing this project Run As -> Java Application

I am using Postman as a REST Client to hit the REST services.

1. http://localhost:8989/rest/allemps -> To get all the existing employees from DB. I have already inserted few records.




2. SAVE POST Request - http://localhost:8989/rest/save
JSON Data Format.{ "firstName": "gaurav", "lastName": "kumar", "email": "admin@gmail.com", "designation": "Lead Development"}


3. Employee By ID - http://localhost:8989/rest/emp/{ID}



Saturday 4 August 2018

About Memory Dumps and Commands

Java Heap Memory



Most of the newly created objects are located in the Eden Memory space


  • When Eden space is filled with objects, Minor GC is performed and all the survivor objects are moved to one of the survivor spaces. Objects not being unreferenced will be copied by the new generation garbage collector into the survivor spaces.
  • Minor GC also checks the survivor objects and moves them to the other survivor space. So at a time, one of the survivor space is always empty. They may get copied in some special cases directly into the old generation pool.
  • Objects that have survived many cycles of GC, are moved to the Old generation memory space. Usually it is done by setting a threshold for the age of the nursery objects before they become eligible to promote to old generation.
  • When the old generation becomes full, garbage is collected there and the process is called as old collection. Old generation memory contains the objects that are long lived and survived after many rounds of Minor GC
  • Usually garbage collection is performed in Old generation memory when it’s full. Old generation garbage collection is called as Major GC and usually takes longer time.
  • Permanent Generation or “Perm Gen” contains the application metadata required by the JVM to describe the classes and methods used in the application. Perm Gen is populated by JVM at runtime based on the classes used by the application. Perm Gen also contains Java SE library classes and methods. Perm Gen objects are garbage collected in a full garbage collection.


<JAVA_HOME>/bin/jstat –gc <JAVA_PID>

Example - C:\Program Files\Java\jdk1.8.0_151\bin>jstat -gc 30372







JMAP

The jmap utility prints the memory-related statistics for a running VM or core file. 

<JAVA_HOME>/bin/jmap –heap <JAVA_PID>

Example: C:\Program Files\Java\jdk1.8.0_151\bin>jmap -heap 30372

Command for Creating HPROF file

C:\Program Files\Java\jdk1.8.0_151\bin>jmap -dump:file=c:\Tutorials\heap-dump.prof 30372




Ques:- How to Get the heap dump using JMap command?
Answer:- 



jcmd


jcmd <JAVA_PID> GC.heap_dump filename=<FILE>

The jcmd utility is used to send diagnostic command requests to the JVM, where these requests are useful for controlling Java Flight Recordings, troubleshoot, and diagnose JVM and Java applications. It must be used on the same machine where the JVM is running, and have same effective user and group identifiers that were used to launch the JVM.

jhat

The jhat tool provides a convenient means to browse the object topology in a heap snapshot. This tool replaces the Heap Analysis Tool (HAT). The tool parses a heap dump in binary format (for example, a heap dump produced by jcmd).

Command

C:\Program Files\Java\jdk1.8.0_151\bin>jhat c:\Tutorials\heap-dump.prof