package com.nirmal.springbootrest.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* Model class for map the BOOK table using Hibernate
* @author Nirmal Balasooriya
*
*/
@Entity
@Table(name = "book")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name="ISBMNUMBER")
private String isbmNumber;
private String name;
private String description;
private String auther;
/**
* This is auto generated id from database
* @return the id
*/
public int getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* @return the isbmNumber
*/
public String getIsbmNumber() {
return isbmNumber;
}
/**
* @param isbmNumber the isbmNumber to set
*/
public void setIsbmNumber(String isbmNumber) {
this.isbmNumber = isbmNumber;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the description
*/
public String getDescription() {
return description;
}
/**
* @param description the description to set
*/
public void setDescription(String description) {
this.description = description;
}
/**
* @return the auther
*/
public String getAuther() {
return auther;
}
/**
* @param auther the auther to set
*/
public void setAuther(String auther) {
this.auther = auther;
}
/**
* @param isbmNumber
* @param name
*/
public Book(String isbmNumber, String name) {
super();
this.isbmNumber = isbmNumber;
this.name = name;
}
/**
* @param isbmNumber
* @param name
* @param description
* @param auther
*/
public Book(String isbmNumber, String name, String description, String auther) {
super();
this.isbmNumber = isbmNumber;
this.name = name;
this.description = description;
this.auther = auther;
}
/**
*
*/
public Book() {
super();
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((isbmNumber == null) ? 0 : isbmNumber.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Book other = (Book) obj;
if (isbmNumber == null) {
if (other.isbmNumber != null)
return false;
} else if (!isbmNumber.equals(other.isbmNumber))
return false;
return true;
}
}
Note that I have added additional two methods in to model class those and hashCode and equels methods. Since im going to keep isbmNumber as unique key in the API I will used it to do the comparer the Book objects in the system.
Creating Spring Data dto
Let create interface for bookDto with following content. In my example table primary key is not the field I use to identify the Book on the system. So because of that I had to add additional method to query database from isbmNumber.I have provide interface name as "IBookDto' and package as "com.nirmal.springbootrest.dto".
package com.nirmal.springbootrest.dto;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.nirmal.springbootrest.model.Book;
/**
* Book DTO
*
* @author Nirmal Balasooriya
*
*/
@Repository
public interface IBookDto extends CrudRepository<Book,Integer> {
public Book getBookByIsbmNumber(String isbmNumber);
@Transactional
@Modifying
@Query(value="delete from Book u where u.isbmNumber = ?1")
void deleteByIsbmNumber(@Param("isbmNumber") String isbmNumber);
}
Creating Book service
Let create interface for Book Service by right click on project and New - > Interface and provide interface name as "IBookService' and package as "om.nirmal.springbootrest.service".
package com.nirmal.springbootrest.service;
import org.springframework.stereotype.Component;
import com.nirmal.springbootrest.model.Book;
/**
* BookService interfacce with abstract methods about Book Service
*
* @author Nirmal Balasooriya
*
*/
@Component
public interface IBookService {
/**
* to save or update the book on database
*
* @param book
* @return bookIsbm
*/
public String saveOrUpdateBook(Book book);
/**
* to retrive the book from database
*
* @param String String
* @return book
*/
public Book getBook(String isbm);
/**
* Delete Book on database
* @param isbm
*/
public void deleteBook(String isbm);
}
Then lets create BookService actual implementation. Lets add new class with name as "BookServiceImpl" and package as "com.nirmal.springbootrest.service".
package com.nirmal.springbootrest.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.nirmal.springbootrest.dto.IBookDto;
import com.nirmal.springbootrest.model.Book;
/**
* Actual implementation of IBookService
*
* @author Nirmal Balasooriya
*
*/
@Service
public class BookServiceImpl implements IBookService {
@Autowired
IBookDto bookDto;
/*
* (non-Javadoc)
*
* @see
* com.nirmal.springbootrest.service.IBookService#saveOrUpdateBook(com.nirmal.
* springbootrest.model.Book)
*/
public String saveOrUpdateBook(Book book) {
Book bookindb=bookDto.getBookByIsbmNumber(book.getIsbmNumber());
if(bookindb!=null) {
book.setId(bookindb.getId());
}
bookindb = bookDto.save(book);
if (bookindb != null)
return bookindb.getIsbmNumber();
return null;
}
/*
* (non-Javadoc)
*
* @see com.nirmal.springbootrest.service.IBookService#getBook(String)
*/
public Book getBook(String isbm) {
Book saveBook = bookDto.getBookByIsbmNumber(isbm);
return saveBook;
}
@Override
public void deleteBook(String isbm) {
bookDto.deleteByIsbmNumber(isbm);
}
}
Creating REST controller for the API
First of all lets create common Response object for our REST API. I will name the class as "Response" inside "com.nirmal.springbootres.controller" package. As you can see I have use generic in order to return different objects on different API calls.
package com.nirmal.springbootrest.controller;
/**
*
* @author Nirmal Balasooriya
*
* @param <T>
*/
public class Response<T> {
private String code;
private String desc;
private T t;
/**
* @return the code
*/
public String getCode() {
return code;
}
/**
* @param code the code to set
*/
public void setCode(String code) {
this.code = code;
}
/**
* @return the desc
*/
public String getDesc() {
return desc;
}
/**
* @param desc the desc to set
*/
public void setDesc(String desc) {
this.desc = desc;
}
/**
* @return the t
*/
public T getT() {
return t;
}
/**
* @param t the t to set
*/
public void setT(T t) {
this.t = t;
}
/**
* @param code
* @param desc
* @param t
*/
public Response(String code, String desc, T t) {
super();
this.code = code;
this.desc = desc;
this.t = t;
}
}
Then lets add the REST controller to our application. I will set controller class name as "BookStoreController" and package name as "com.nirmal.springbootres.controller".
package com.nirmal.springbootrest.controller;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
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.ResponseBody;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nirmal.springbootrest.model.Book;
import com.nirmal.springbootrest.service.IBookService;
/**
* Represent the REST controller for the application
*
* @author Nirmal Balasooriya
*
*/
@Controller
@Component
public class BookStoreController {
Logger logger = LoggerFactory.getLogger(BookStoreController.class);
@Autowired
IBookService iBookService;
@GetMapping("/findBook/{isbm}")
@ResponseBody
public Response<Book> findBook(@PathVariable("isbm")String isbm) {
logger.info("Book find isbm : " + isbm);
Book book = iBookService.getBook(isbm);
Response<Book> response = new Response<Book>("0", "Book can not be found", null);
if (book != null)
response = new Response<Book>("1", "Book found", book);
return response;
}
@RequestMapping(method = RequestMethod.POST, value = "/saveOrUpdate")
@ResponseBody
public Response<String> saveBookInJSON(@RequestBody Book book) {
logger.info("Book saved request" + book);
Response<String> response;
if ((book.getIsbmNumber() == null) || (book.getIsbmNumber() != null && book.getIsbmNumber().trim().isEmpty())) {
logger.info("Book saved fail ISBM_IS_MANDOTORY");
response = new Response<String>("0", "Book save faild ISBM mandotory", null);
} else if ((book.getName() == null) || (book.getName() != null && book.getName().trim().isEmpty())) {
logger.info("Book saved failed BOOK_NAME_IS_MANDOTORY");
response = new Response<String>("0", "Book save failed name mandotory", null);
} else {
try {
String savedbook = iBookService.saveOrUpdateBook(book);
response = new Response<String>("1", "Book save successful", savedbook);
logger.info("Book saved sucess" + savedbook);
} catch (Exception e) {
logger.error("Book saved failed" + e.getMessage());
response = new Response<String>("1", "Book save successful", null);
}
}
return response;
}
@RequestMapping(method = RequestMethod.POST, value = "/deleteBook")
@ResponseBody
public Response<String> deleteBookInJSON(@RequestBody String isbm) throws IOException {
logger.info("Book selete request" + isbm);
ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree(isbm);
Response<String> response;
isbm = actualObj.get("isbm").asText();
if ((isbm == null) || (isbm != null && isbm.trim().isEmpty())) {
logger.info("Book saved fail ISBM_IS_MANDOTORY");
response = new Response<String>("0", "Book delete faild ISBM mandotory", null);
} else {
try {
iBookService.deleteBook(isbm);
response = new Response<String>("1", "Book delete successful", isbm);
logger.info("Book delete sucess" + isbm);
} catch (Exception e) {
e.printStackTrace();
logger.error("Book delete failed" + e.getMessage());
response = new Response<String>("0", "Book delete fail", null);
}
}
return response;
}
}
After define the controller now we are ready with our REST API. Lets perform maven install and go to the target folder then lets run the jar file using bellow command.
java -jar RestApiSpringBoot-0.0.1-SNAPSHOT.jar
Then open new command line interface and lets run following curl command to test our API.
curl -X GET http://localhost:8080/findBook/9999
Then you should get following output as result
{"code":"0","desc":"Book can not be found","t":null}
Then lets add new Book in to API
curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d "{ \"isbmNumber\":\"9999\", \"name\":\"How to develop API\", \"description\":\"sample book\", \"auther\":\"Nirmal Balasooriya \" }" http://localhost:8080/saveOrUpdate
For this one following output will return
{"code":"1","desc":"Book save successful","t":"9999"}
Then if we perform previous curl command again now you will be get following output from the API.
{"code":"1","desc":"Book found","t":{"id":8,"isbmNumber":"9999","name":"How to develop API","description":"sample book","auther":"Nirmal Balasooriya "}}
Then lets try on delete operation
curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d "{ \"isbm\":\"9999\" }" http://localhost:8080/deleteBook
Then you can see output as follows
{"code":"1","desc":"Book delete successful","t":"9999"}