├── src ├── main │ ├── java │ │ └── com │ │ │ └── mightyjava │ │ │ ├── exception │ │ │ ├── ApplicationException.java │ │ │ ├── BookNotFoundException.java │ │ │ ├── BookCustomExceptionHandler.java │ │ │ └── BookExceptionHandler.java │ │ │ ├── service │ │ │ ├── IService.java │ │ │ └── impl │ │ │ │ ├── BookServiceImpl.java │ │ │ │ ├── RoleServiceImpl.java │ │ │ │ ├── UserServiceImpl.java │ │ │ │ └── UserDetailsServiceImpl.java │ │ │ ├── repository │ │ │ ├── RoleRepository.java │ │ │ ├── BookRepository.java │ │ │ └── UserRepository.java │ │ │ ├── ServletInitializer.java │ │ │ ├── filter │ │ │ ├── FilterConfig.java │ │ │ ├── ActuatorFilter.java │ │ │ ├── BookFilterTwo.java │ │ │ └── BookFilter.java │ │ │ ├── interceptor │ │ │ ├── BookInterceptorConfig.java │ │ │ └── BookInterceptor.java │ │ │ ├── util │ │ │ └── MethodUtils.java │ │ │ ├── domain │ │ │ ├── Role.java │ │ │ ├── User.java │ │ │ └── Book.java │ │ │ ├── config │ │ │ ├── JwtTokenConfigurer.java │ │ │ ├── SpringSecurityConfig.java │ │ │ ├── JwtTokenProvider.java │ │ │ └── JwtTokenFilter.java │ │ │ ├── resource │ │ │ ├── Resource.java │ │ │ └── impl │ │ │ │ ├── UserResourceImpl.java │ │ │ │ └── BookResourceImpl.java │ │ │ └── Application.java │ └── resources │ │ └── application.properties └── test │ └── java │ └── com │ └── mightyjava │ └── ApplicationTests.java ├── README.md └── pom.xml /src/main/java/com/mightyjava/exception/ApplicationException.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.exception; 2 | 3 | public class ApplicationException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = -3101984166649269624L; 6 | 7 | public ApplicationException(String message) { 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/exception/BookNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.exception; 2 | 3 | public class BookNotFoundException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = -2533194229906054487L; 6 | 7 | public BookNotFoundException(String message) { 8 | super(message); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/service/IService.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.service; 2 | 3 | import java.util.Collection; 4 | import java.util.Optional; 5 | 6 | public interface IService { 7 | Collection findAll(); 8 | 9 | Optional findById(Long id); 10 | 11 | T saveOrUpdate(T t); 12 | 13 | String deleteById(Long id); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/repository/RoleRepository.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | import com.mightyjava.domain.Role; 7 | 8 | @Repository 9 | public interface RoleRepository extends JpaRepository { 10 | 11 | } -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/repository/BookRepository.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | import com.mightyjava.domain.Book; 7 | 8 | @Repository 9 | public interface BookRepository extends JpaRepository { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/test/java/com/mightyjava/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8081 2 | server.servlet.context-path=/rest 3 | 4 | #H2 5 | spring.h2.console.enabled=true 6 | spring.h2.console.path=/h2 7 | 8 | spring.datasource.url=jdbc:h2:~/book-db 9 | spring.datasource.driver-class-name=org.h2.Driver 10 | spring.datasource.username=sa 11 | spring.datasource.password= 12 | 13 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect 14 | 15 | #JWT 16 | jwt.secret-key=almightyjava -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | @Override 9 | protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { 10 | return builder.sources(Application.class); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.data.jpa.repository.Query; 5 | import org.springframework.data.repository.query.Param; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import com.mightyjava.domain.User; 9 | 10 | @Repository 11 | public interface UserRepository extends JpaRepository { 12 | 13 | @Query("FROM User WHERE email=:email") 14 | User findByEmail(@Param("email") String email); 15 | } -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/filter/FilterConfig.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.filter; 2 | 3 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Configuration 8 | public class FilterConfig { 9 | 10 | @Bean 11 | public FilterRegistrationBean registrationBean() { 12 | FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); 13 | registrationBean.setFilter(new ActuatorFilter()); 14 | registrationBean.addUrlPatterns("/actuator/*"); 15 | return registrationBean; 16 | } 17 | } -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/interceptor/BookInterceptorConfig.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.interceptor; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Component; 5 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; 7 | 8 | @Component 9 | public class BookInterceptorConfig extends WebMvcConfigurationSupport { 10 | 11 | @Autowired 12 | private BookInterceptor bookInterceptor; 13 | 14 | @Override 15 | protected void addInterceptors(InterceptorRegistry registry) { 16 | registry.addInterceptor(bookInterceptor); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/util/MethodUtils.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.util; 2 | 3 | import org.codehaus.jettison.json.JSONException; 4 | import org.codehaus.jettison.json.JSONObject; 5 | import org.springframework.http.HttpStatus; 6 | 7 | public class MethodUtils { 8 | 9 | private MethodUtils() { 10 | } 11 | 12 | public static String prepareErrorJSON(HttpStatus status, Exception ex) { 13 | JSONObject errorJSON = new JSONObject(); 14 | try { 15 | errorJSON.put("status", status.value()); 16 | errorJSON.put("error", status.getReasonPhrase()); 17 | errorJSON.put("message", ex.getMessage().split(":")[0]); 18 | } catch (JSONException e) { 19 | e.printStackTrace(); 20 | } 21 | return errorJSON.toString(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/filter/ActuatorFilter.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.filter; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.Filter; 6 | import javax.servlet.FilterChain; 7 | import javax.servlet.ServletException; 8 | import javax.servlet.ServletRequest; 9 | import javax.servlet.ServletResponse; 10 | 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.stereotype.Component; 14 | 15 | @Component 16 | public class ActuatorFilter implements Filter { 17 | 18 | private static Logger log = LoggerFactory.getLogger(ActuatorFilter.class); 19 | 20 | @Override 21 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 22 | throws IOException, ServletException { 23 | log.info("ActuatorFilter - doFilter"); 24 | chain.doFilter(request, response); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/domain/Role.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.domain; 2 | 3 | import java.util.Set; 4 | 5 | import javax.persistence.CascadeType; 6 | import javax.persistence.Entity; 7 | import javax.persistence.FetchType; 8 | import javax.persistence.GeneratedValue; 9 | import javax.persistence.Id; 10 | import javax.persistence.OneToMany; 11 | import javax.validation.constraints.NotNull; 12 | 13 | @Entity 14 | public class Role { 15 | @Id 16 | @GeneratedValue 17 | private Long id; 18 | private String name; 19 | 20 | @OneToMany(targetEntity = User.class, mappedBy = "role", fetch = FetchType.LAZY, cascade = CascadeType.ALL) 21 | private Set users; 22 | 23 | public Role() { 24 | } 25 | 26 | public Role(Long id, @NotNull String name) { 27 | this.id = id; 28 | this.name = name; 29 | } 30 | 31 | public String getName() { 32 | return name; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/config/JwtTokenConfigurer.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.config; 2 | 3 | import org.springframework.security.config.annotation.SecurityConfigurerAdapter; 4 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 5 | import org.springframework.security.web.DefaultSecurityFilterChain; 6 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 7 | 8 | public class JwtTokenConfigurer extends SecurityConfigurerAdapter { 9 | 10 | private JwtTokenProvider tokenProvider; 11 | 12 | public JwtTokenConfigurer(JwtTokenProvider tokenProvider) { 13 | this.tokenProvider = tokenProvider; 14 | } 15 | 16 | @Override 17 | public void configure(HttpSecurity http) throws Exception { 18 | http.addFilterBefore(new JwtTokenFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/filter/BookFilterTwo.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.filter; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.Filter; 6 | import javax.servlet.FilterChain; 7 | import javax.servlet.ServletException; 8 | import javax.servlet.ServletRequest; 9 | import javax.servlet.ServletResponse; 10 | 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.core.annotation.Order; 14 | import org.springframework.stereotype.Component; 15 | 16 | @Component 17 | @Order(1) 18 | public class BookFilterTwo implements Filter { 19 | 20 | private static Logger log = LoggerFactory.getLogger(BookFilterTwo.class); 21 | 22 | @Override 23 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 24 | throws IOException, ServletException { 25 | log.info("BookFilterTwo - doFilter"); 26 | chain.doFilter(request, response); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/exception/BookCustomExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.web.bind.annotation.ControllerAdvice; 6 | import org.springframework.web.bind.annotation.ExceptionHandler; 7 | 8 | import com.mightyjava.util.MethodUtils; 9 | 10 | @ControllerAdvice 11 | public class BookCustomExceptionHandler { 12 | 13 | @ExceptionHandler(value = ApplicationException.class) 14 | public ResponseEntity applicationException(ApplicationException exception) { 15 | HttpStatus status = HttpStatus.BAD_REQUEST; 16 | return new ResponseEntity<>(MethodUtils.prepareErrorJSON(status, exception), status); 17 | } 18 | 19 | @ExceptionHandler(value = BookNotFoundException.class) 20 | public ResponseEntity bookNotFoundException(BookNotFoundException exception) { 21 | HttpStatus status = HttpStatus.NOT_FOUND; 22 | return new ResponseEntity<>(MethodUtils.prepareErrorJSON(status, exception), status); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/exception/BookExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.exception; 2 | 3 | import org.springframework.http.HttpHeaders; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.http.converter.HttpMessageNotReadableException; 7 | import org.springframework.web.bind.annotation.ControllerAdvice; 8 | import org.springframework.web.context.request.WebRequest; 9 | import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; 10 | 11 | import com.mightyjava.util.MethodUtils; 12 | 13 | @ControllerAdvice 14 | public class BookExceptionHandler extends ResponseEntityExceptionHandler { 15 | 16 | @Override 17 | protected ResponseEntity handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, 18 | HttpStatus status, WebRequest request) { 19 | return new ResponseEntity<>(MethodUtils.prepareErrorJSON(status, ex), status); 20 | } 21 | 22 | @Override 23 | protected ResponseEntity handleHttpMessageNotReadable(HttpMessageNotReadableException ex, 24 | HttpHeaders headers, HttpStatus status, WebRequest request) { 25 | return new ResponseEntity<>(MethodUtils.prepareErrorJSON(status, ex), status); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/service/impl/BookServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.service.impl; 2 | 3 | import java.util.Collection; 4 | import java.util.Optional; 5 | 6 | import org.codehaus.jettison.json.JSONException; 7 | import org.codehaus.jettison.json.JSONObject; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | import com.mightyjava.domain.Book; 12 | import com.mightyjava.repository.BookRepository; 13 | import com.mightyjava.service.IService; 14 | 15 | @Service 16 | public class BookServiceImpl implements IService { 17 | 18 | @Autowired 19 | private BookRepository bookRepository; 20 | 21 | @Override 22 | public Collection findAll() { 23 | return bookRepository.findAll(); 24 | } 25 | 26 | @Override 27 | public Optional findById(Long id) { 28 | return bookRepository.findById(id); 29 | } 30 | 31 | @Override 32 | public Book saveOrUpdate(Book book) { 33 | return bookRepository.saveAndFlush(book); 34 | } 35 | 36 | @Override 37 | public String deleteById(Long id) { 38 | JSONObject jsonObject = new JSONObject(); 39 | try { 40 | bookRepository.deleteById(id); 41 | jsonObject.put("message", "Book deleted successfully"); 42 | } catch (JSONException e) { 43 | e.printStackTrace(); 44 | } 45 | return jsonObject.toString(); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/service/impl/RoleServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.service.impl; 2 | 3 | import java.util.Collection; 4 | import java.util.Optional; 5 | 6 | import org.codehaus.jettison.json.JSONException; 7 | import org.codehaus.jettison.json.JSONObject; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | import com.mightyjava.domain.Role; 12 | import com.mightyjava.repository.RoleRepository; 13 | import com.mightyjava.service.IService; 14 | 15 | @Service 16 | public class RoleServiceImpl implements IService { 17 | 18 | @Autowired 19 | private RoleRepository roleRepository; 20 | 21 | @Override 22 | public Collection findAll() { 23 | return roleRepository.findAll(); 24 | } 25 | 26 | @Override 27 | public Optional findById(Long id) { 28 | return roleRepository.findById(id); 29 | } 30 | 31 | @Override 32 | public Role saveOrUpdate(Role role) { 33 | return roleRepository.saveAndFlush(role); 34 | } 35 | 36 | @Override 37 | public String deleteById(Long id) { 38 | JSONObject jsonObject = new JSONObject(); 39 | try { 40 | roleRepository.deleteById(id); 41 | jsonObject.put("message", "Role deleted successfully"); 42 | } catch (JSONException e) { 43 | e.printStackTrace(); 44 | } 45 | return jsonObject.toString(); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.service.impl; 2 | 3 | import java.util.Collection; 4 | import java.util.Optional; 5 | 6 | import org.codehaus.jettison.json.JSONException; 7 | import org.codehaus.jettison.json.JSONObject; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | import com.mightyjava.domain.User; 12 | import com.mightyjava.repository.UserRepository; 13 | import com.mightyjava.service.IService; 14 | 15 | @Service 16 | public class UserServiceImpl implements IService { 17 | 18 | @Autowired 19 | private UserRepository userRepository; 20 | 21 | @Override 22 | public Collection findAll() { 23 | return userRepository.findAll(); 24 | } 25 | 26 | @Override 27 | public Optional findById(Long id) { 28 | return userRepository.findById(id); 29 | } 30 | 31 | @Override 32 | public User saveOrUpdate(User user) { 33 | return userRepository.saveAndFlush(user); 34 | } 35 | 36 | @Override 37 | public String deleteById(Long id) { 38 | JSONObject jsonObject = new JSONObject(); 39 | try { 40 | userRepository.deleteById(id); 41 | jsonObject.put("message", "User deleted successfully"); 42 | } catch (JSONException e) { 43 | e.printStackTrace(); 44 | } 45 | return jsonObject.toString(); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/filter/BookFilter.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.filter; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.Filter; 6 | import javax.servlet.FilterChain; 7 | import javax.servlet.ServletException; 8 | import javax.servlet.ServletRequest; 9 | import javax.servlet.ServletResponse; 10 | 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.core.annotation.Order; 14 | import org.springframework.stereotype.Component; 15 | 16 | @Component 17 | @Order(2) 18 | public class BookFilter implements Filter { 19 | 20 | private static Logger log = LoggerFactory.getLogger(BookFilter.class); 21 | 22 | @Override 23 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 24 | throws IOException, ServletException { 25 | log.info("BookFilter - doFilter"); 26 | // log.info("Local Port - " + request.getLocalPort()); 27 | // log.info("Server Name - " + request.getServerName()); 28 | // log.info("Protocol - " + request.getProtocol()); 29 | // HttpServletRequest httpServletRequest = (HttpServletRequest) request; 30 | // log.info("Method - " + httpServletRequest.getMethod()); 31 | // log.info("Request URI - " + httpServletRequest.getRequestURI()); 32 | // log.info("Servlet Path - " + httpServletRequest.getServletPath()); 33 | chain.doFilter(request, response); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/resource/Resource.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.resource; 2 | 3 | import java.util.Collection; 4 | 5 | import org.springframework.http.MediaType; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.security.access.prepost.PreAuthorize; 8 | import org.springframework.web.bind.annotation.DeleteMapping; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.PathVariable; 11 | import org.springframework.web.bind.annotation.PostMapping; 12 | import org.springframework.web.bind.annotation.PutMapping; 13 | import org.springframework.web.bind.annotation.RequestBody; 14 | 15 | public interface Resource { 16 | @GetMapping 17 | @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER')") 18 | ResponseEntity> findAll(); 19 | 20 | @GetMapping("{id}") 21 | ResponseEntity findById(@PathVariable Long id); 22 | 23 | @PostMapping(consumes = MediaType.APPLICATION_JSON_UTF8_VALUE) 24 | @PreAuthorize("hasRole('ROLE_ADMIN')") 25 | ResponseEntity save(@RequestBody T t); 26 | 27 | @PutMapping(consumes = MediaType.APPLICATION_JSON_UTF8_VALUE) 28 | @PreAuthorize("hasRole('ROLE_ADMIN')") 29 | ResponseEntity update(@RequestBody T t); 30 | 31 | @DeleteMapping("{id}") 32 | @PreAuthorize("hasRole('ROLE_ADMIN')") 33 | ResponseEntity deleteById(@PathVariable Long id); 34 | 35 | @GetMapping("/invalid") 36 | ResponseEntity invalid(); 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/domain/User.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.domain; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.Id; 6 | import javax.persistence.JoinColumn; 7 | import javax.persistence.ManyToOne; 8 | import javax.validation.constraints.NotNull; 9 | 10 | @Entity 11 | public class User { 12 | @Id 13 | @GeneratedValue 14 | private Long id; 15 | @NotNull 16 | private String name; 17 | @NotNull 18 | private String email; 19 | @NotNull 20 | private String mobile; 21 | @NotNull 22 | private String password; 23 | @ManyToOne 24 | @JoinColumn(name = "role_id") 25 | private Role role; 26 | 27 | public Long getId() { 28 | return id; 29 | } 30 | 31 | public void setId(Long id) { 32 | this.id = id; 33 | } 34 | 35 | public String getName() { 36 | return name; 37 | } 38 | 39 | public void setName(String name) { 40 | this.name = name; 41 | } 42 | 43 | public String getEmail() { 44 | return email; 45 | } 46 | 47 | public void setEmail(String email) { 48 | this.email = email; 49 | } 50 | 51 | public String getMobile() { 52 | return mobile; 53 | } 54 | 55 | public void setMobile(String mobile) { 56 | this.mobile = mobile; 57 | } 58 | 59 | public String getPassword() { 60 | return password; 61 | } 62 | 63 | public void setPassword(String password) { 64 | this.password = password; 65 | } 66 | 67 | public Role getRole() { 68 | return role; 69 | } 70 | 71 | public void setRole(Role role) { 72 | this.role = role; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/service/impl/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.service.impl; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.security.core.GrantedAuthority; 8 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 9 | import org.springframework.security.core.userdetails.UserDetails; 10 | import org.springframework.security.core.userdetails.UserDetailsService; 11 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 12 | import org.springframework.stereotype.Service; 13 | 14 | import com.mightyjava.domain.User; 15 | import com.mightyjava.repository.UserRepository; 16 | 17 | @Service 18 | public class UserDetailsServiceImpl implements UserDetailsService { 19 | 20 | @Autowired 21 | private UserRepository userRepository; 22 | 23 | @Override 24 | public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { 25 | User user = userRepository.findByEmail(email); 26 | if (user == null) { 27 | throw new UsernameNotFoundException("Email " + email + " not found"); 28 | } 29 | return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), 30 | getGrantedAuthority(user)); 31 | } 32 | 33 | private Collection getGrantedAuthority(User user) { 34 | Collection authorities = new ArrayList<>(); 35 | if (user.getRole().getName().equalsIgnoreCase("admin")) { 36 | authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN")); 37 | } 38 | authorities.add(new SimpleGrantedAuthority("ROLE_USER")); 39 | return authorities; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/domain/Book.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.domain; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.Id; 6 | import javax.validation.constraints.NotNull; 7 | 8 | @Entity 9 | public class Book { 10 | 11 | @Id 12 | @GeneratedValue 13 | private Long id; 14 | 15 | @NotNull 16 | private String title; 17 | 18 | @NotNull 19 | private String author; 20 | 21 | @NotNull 22 | private String coverPhotoURL; 23 | 24 | @NotNull 25 | private Long isbnNumber; 26 | 27 | @NotNull 28 | private Double price; 29 | 30 | @NotNull 31 | private String language; 32 | 33 | public Long getId() { 34 | return id; 35 | } 36 | 37 | public void setId(Long id) { 38 | this.id = id; 39 | } 40 | 41 | public String getTitle() { 42 | return title; 43 | } 44 | 45 | public void setTitle(String title) { 46 | this.title = title; 47 | } 48 | 49 | public String getAuthor() { 50 | return author; 51 | } 52 | 53 | public void setAuthor(String author) { 54 | this.author = author; 55 | } 56 | 57 | public String getCoverPhotoURL() { 58 | return coverPhotoURL; 59 | } 60 | 61 | public void setCoverPhotoURL(String coverPhotoURL) { 62 | this.coverPhotoURL = coverPhotoURL; 63 | } 64 | 65 | public Long getIsbnNumber() { 66 | return isbnNumber; 67 | } 68 | 69 | public void setIsbnNumber(Long isbnNumber) { 70 | this.isbnNumber = isbnNumber; 71 | } 72 | 73 | public Double getPrice() { 74 | return price; 75 | } 76 | 77 | public void setPrice(Double price) { 78 | this.price = price; 79 | } 80 | 81 | public String getLanguage() { 82 | return language; 83 | } 84 | 85 | public void setLanguage(String language) { 86 | this.language = language; 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GET 2 | http://localhost:8081/rest/books 3 | 4 | # GET By ID 5 | http://localhost:8081/rest/books/1 6 | 7 | # POST 8 | http://localhost:8081/rest/books 9 | 10 | # PUT 11 | http://localhost:8081/rest/books 12 | 13 | # DELETE 14 | http://localhost:8081/rest/books/1 15 | 16 | # Requests 17 | 18 | { 19 | "title": "Spring in Action", 20 | "author": "Craig Walls", 21 | "coverPhotoURL": "https://images-na.ssl-images-amazon.com/images/I/51gHy16h5TL.jpg", 22 | "isbnNumber": 9789351197997, 23 | "price": 630, 24 | "language": "English" 25 | } 26 | { 27 | "title": "Java Persistence with Hibernate", 28 | "author": "Christian Bauer and Gavin King", 29 | "coverPhotoURL": "https://images.manning.com/720/960/resize/book/d/2ea186d-c683-4d54-95f9-cca25b6fe49e/bauer2.png", 30 | "isbnNumber": 9351199193, 31 | "price": 771, 32 | "language": "English" 33 | } 34 | { 35 | "title": "Grails in Action", 36 | "author": "Glen Smith and Peter Ledbrook", 37 | "coverPhotoURL": "https://images.manning.com/720/960/resize/book/6/3e9d5ed-4155-466d-ab46-538bb355948d/gsmith2.png", 38 | "isbnNumber": 1617290963, 39 | "price": 2907, 40 | "language": "English" 41 | } 42 | { 43 | "title": "Spring Boot in Action", 44 | "author": "Craig Walls", 45 | "coverPhotoURL": "https://images.manning.com/720/960/resize/book/6/bb80688-f898-4df7-838a-253b1de123c4/Walls-SpringBoot-HI.png", 46 | "isbnNumber": 1617292540, 47 | "price": 3149, 48 | "language": "English" 49 | } 50 | { 51 | "title": "Head First Java: A Brain-Friendly Guide", 52 | "author": "Kathy Sierra", 53 | "coverPhotoURL": "https://covers.oreillystatic.com/images/9780596004651/lrg.jpg", 54 | "isbnNumber": 8173666024, 55 | "price": 498, 56 | "language": "English" 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/config/SpringSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.security.authentication.AuthenticationManager; 7 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 8 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 10 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 11 | import org.springframework.security.config.http.SessionCreationPolicy; 12 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 13 | import org.springframework.security.crypto.password.PasswordEncoder; 14 | 15 | @Configuration 16 | @EnableWebSecurity 17 | @EnableGlobalMethodSecurity(prePostEnabled = true) 18 | public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { 19 | 20 | @Autowired 21 | private JwtTokenProvider tokenProvider; 22 | 23 | @Bean 24 | public PasswordEncoder passwordEncoder() { 25 | return new BCryptPasswordEncoder(); 26 | } 27 | 28 | @Bean 29 | @Override 30 | public AuthenticationManager authenticationManagerBean() throws Exception { 31 | return super.authenticationManagerBean(); 32 | } 33 | 34 | @Override 35 | protected void configure(HttpSecurity http) throws Exception { 36 | http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() 37 | .authorizeRequests().antMatchers("/user/authenticate").permitAll().anyRequest().authenticated(); 38 | http.apply(new JwtTokenConfigurer(tokenProvider)); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/interceptor/BookInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.interceptor; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | import javax.servlet.http.HttpServletResponse; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.stereotype.Component; 9 | import org.springframework.web.servlet.HandlerInterceptor; 10 | import org.springframework.web.servlet.ModelAndView; 11 | 12 | @Component 13 | public class BookInterceptor implements HandlerInterceptor { 14 | 15 | private static Logger log = LoggerFactory.getLogger(BookInterceptor.class); 16 | 17 | @Override 18 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 19 | throws Exception { 20 | log.info("BookInterceptor - preHandle"); 21 | // boolean flag = true; 22 | // String method = request.getMethod(); 23 | // int contentLength =request.getContentLength(); 24 | // if(method.equalsIgnoreCase("post") || method.equalsIgnoreCase("put")) { 25 | // String contentType = request.getContentType(); 26 | // if(contentType != null && !contentType.equalsIgnoreCase("application/json")) { 27 | // flag = false; 28 | // } 29 | // else if(contentLength <= 2) { 30 | // flag = false; 31 | // } 32 | // } 33 | // if(!flag) { 34 | // response.sendRedirect("/rest/books/invalid"); 35 | // } 36 | // return flag; 37 | return HandlerInterceptor.super.preHandle(request, response, handler); 38 | } 39 | 40 | @Override 41 | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 42 | ModelAndView modelAndView) throws Exception { 43 | log.info("BookInterceptor - postHandle"); 44 | HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); 45 | } 46 | 47 | @Override 48 | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 49 | throws Exception { 50 | log.info("BookInterceptor - afterCompletion"); 51 | HandlerInterceptor.super.afterCompletion(request, response, handler, ex); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/Application.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.CommandLineRunner; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 8 | 9 | import com.mightyjava.domain.Book; 10 | import com.mightyjava.domain.Role; 11 | import com.mightyjava.domain.User; 12 | import com.mightyjava.service.IService; 13 | 14 | @SpringBootApplication 15 | public class Application implements CommandLineRunner { 16 | 17 | @Autowired 18 | private IService bookService; 19 | @Autowired 20 | private IService userService; 21 | @Autowired 22 | private IService roleService; 23 | 24 | public static void main(String[] args) { 25 | SpringApplication.run(Application.class, args); 26 | } 27 | 28 | @Override 29 | public void run(String... args) throws Exception { 30 | roleService.saveOrUpdate(new Role(1L, "admin")); 31 | roleService.saveOrUpdate(new Role(2L, "user")); 32 | 33 | User user1 = new User(); 34 | user1.setEmail("test@user.com"); 35 | user1.setName("Test User"); 36 | user1.setMobile("9787456545"); 37 | user1.setRole(roleService.findById(2L).get()); 38 | user1.setPassword(new BCryptPasswordEncoder().encode("testuser")); 39 | userService.saveOrUpdate(user1); 40 | 41 | User user2 = new User(); 42 | user2.setEmail("test@admin.com"); 43 | user2.setName("Test Admin"); 44 | user2.setMobile("9787456545"); 45 | user2.setRole(roleService.findById(1L).get()); 46 | user2.setPassword(new BCryptPasswordEncoder().encode("testadmin")); 47 | userService.saveOrUpdate(user2); 48 | 49 | Book book = new Book(); 50 | book.setTitle("Spring Microservices in Action"); 51 | book.setAuthor("John Carnell"); 52 | book.setCoverPhotoURL("https://images-na.ssl-images-amazon.com/images/I/417zLTa1uqL._SX397_BO1,204,203,200_.jpg"); 53 | book.setIsbnNumber(1617293989L); 54 | book.setPrice(2776.00); 55 | book.setLanguage("English"); 56 | bookService.saveOrUpdate(book); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/config/JwtTokenProvider.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.config; 2 | 3 | import java.io.Serializable; 4 | import java.util.Base64; 5 | import java.util.Date; 6 | 7 | import javax.annotation.PostConstruct; 8 | 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.beans.factory.annotation.Value; 11 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 12 | import org.springframework.security.core.Authentication; 13 | import org.springframework.security.core.userdetails.UserDetails; 14 | import org.springframework.security.core.userdetails.UserDetailsService; 15 | import org.springframework.stereotype.Component; 16 | 17 | import com.mightyjava.domain.Role; 18 | 19 | import io.jsonwebtoken.Claims; 20 | import io.jsonwebtoken.Jwts; 21 | import io.jsonwebtoken.SignatureAlgorithm; 22 | 23 | @Component 24 | public class JwtTokenProvider implements Serializable { 25 | 26 | private static final long serialVersionUID = 2569800841756370596L; 27 | 28 | @Value("${jwt.secret-key}") 29 | private String secretKey; 30 | 31 | @PostConstruct 32 | protected void init() { 33 | secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes()); 34 | } 35 | 36 | private long validityInMilliseconds = 50 * 60 * 60; // 2 minute 37 | 38 | public String createToken(String username, Role role) { 39 | Claims claims = Jwts.claims().setSubject(username); 40 | claims.put("auth", role); 41 | 42 | Date now = new Date(); 43 | return Jwts.builder().setClaims(claims).setIssuedAt(now) 44 | .setExpiration(new Date(now.getTime() + validityInMilliseconds)) 45 | .signWith(SignatureAlgorithm.HS256, secretKey).compact(); 46 | } 47 | 48 | @Autowired 49 | private UserDetailsService userDetailsService; 50 | 51 | public Authentication getAuthentication(String username) { 52 | UserDetails userDetails = userDetailsService.loadUserByUsername(username); 53 | return new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(), 54 | userDetails.getAuthorities()); 55 | } 56 | 57 | public Claims getClaimsFromToken(String token) { 58 | return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody(); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/config/JwtTokenFilter.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.config; 2 | 3 | import java.io.IOException; 4 | import java.util.Date; 5 | 6 | import javax.servlet.FilterChain; 7 | import javax.servlet.ServletException; 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | 11 | import org.codehaus.jettison.json.JSONException; 12 | import org.codehaus.jettison.json.JSONObject; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | import org.springframework.security.core.Authentication; 16 | import org.springframework.security.core.context.SecurityContextHolder; 17 | import org.springframework.web.filter.OncePerRequestFilter; 18 | 19 | import io.jsonwebtoken.Claims; 20 | 21 | public class JwtTokenFilter extends OncePerRequestFilter { 22 | 23 | private static Logger log = LoggerFactory.getLogger(JwtTokenFilter.class); 24 | 25 | private JwtTokenProvider tokenProvider; 26 | 27 | public JwtTokenFilter(JwtTokenProvider tokenProvider) { 28 | this.tokenProvider = tokenProvider; 29 | } 30 | 31 | @Override 32 | public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 33 | throws ServletException, IOException { 34 | log.info("JwtTokenFilter : doFilterInternal"); 35 | String token = request.getHeader("Authorization"); 36 | if (token != null) { 37 | try { 38 | Claims claims = tokenProvider.getClaimsFromToken(token); 39 | if (!claims.getExpiration().before(new Date())) { 40 | Authentication authentication = tokenProvider.getAuthentication(claims.getSubject()); 41 | if (authentication.isAuthenticated()) { 42 | SecurityContextHolder.getContext().setAuthentication(authentication); 43 | } 44 | } 45 | } catch (RuntimeException e) { 46 | try { 47 | SecurityContextHolder.clearContext(); 48 | response.setContentType("application/json"); 49 | response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 50 | response.getWriter().println( 51 | new JSONObject().put("exception", "expired or invalid JWT token " + e.getMessage())); 52 | } catch (IOException | JSONException e1) { 53 | e1.printStackTrace(); 54 | } 55 | return; 56 | } 57 | } else { 58 | log.info("first time so creating token using UserResourceImpl - authenticate method"); 59 | } 60 | filterChain.doFilter(request, response); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/resource/impl/UserResourceImpl.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.resource.impl; 2 | 3 | import org.codehaus.jettison.json.JSONException; 4 | import org.codehaus.jettison.json.JSONObject; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.http.MediaType; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.security.authentication.AuthenticationManager; 12 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 13 | import org.springframework.security.core.Authentication; 14 | import org.springframework.web.bind.annotation.PostMapping; 15 | import org.springframework.web.bind.annotation.RequestBody; 16 | import org.springframework.web.bind.annotation.RequestMapping; 17 | import org.springframework.web.bind.annotation.RestController; 18 | 19 | import com.mightyjava.config.JwtTokenProvider; 20 | import com.mightyjava.domain.User; 21 | import com.mightyjava.repository.UserRepository; 22 | 23 | @RestController 24 | @RequestMapping("/user") 25 | public class UserResourceImpl { 26 | 27 | private static Logger log = LoggerFactory.getLogger(UserResourceImpl.class); 28 | 29 | @Autowired 30 | private AuthenticationManager authenticationManager; 31 | 32 | @Autowired 33 | private JwtTokenProvider tokenProvider; 34 | 35 | @Autowired 36 | private UserRepository userRepository; 37 | 38 | @PostMapping(value = "/authenticate", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) 39 | public ResponseEntity authenticate(@RequestBody User user) { 40 | log.info("UserResourceImpl : authenticate"); 41 | JSONObject jsonObject = new JSONObject(); 42 | try { 43 | Authentication authentication = authenticationManager 44 | .authenticate(new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword())); 45 | if (authentication.isAuthenticated()) { 46 | String email = user.getEmail(); 47 | jsonObject.put("name", authentication.getName()); 48 | jsonObject.put("authorities", authentication.getAuthorities()); 49 | jsonObject.put("token", tokenProvider.createToken(email, userRepository.findByEmail(email).getRole())); 50 | return new ResponseEntity(jsonObject.toString(), HttpStatus.OK); 51 | } 52 | } catch (JSONException e) { 53 | try { 54 | jsonObject.put("exception", e.getMessage()); 55 | } catch (JSONException e1) { 56 | e1.printStackTrace(); 57 | } 58 | return new ResponseEntity(jsonObject.toString(), HttpStatus.UNAUTHORIZED); 59 | } 60 | return null; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.1.3.RELEASE 9 | 10 | 11 | com.mightyjava 12 | book-rest-api-spring-security-jwt 13 | 0.0.1-SNAPSHOT 14 | war 15 | book-rest-api-spring-security-jwt 16 | Integrate Spring Security and JWT with Spring Boot to secure our REST API 17 | 18 | 19 | 1.8 20 | 21 | 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-web 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-tomcat 31 | provided 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-actuator 37 | 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-devtools 42 | runtime 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-starter-data-jpa 48 | 49 | 50 | 51 | com.h2database 52 | h2 53 | runtime 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-starter-test 59 | test 60 | 61 | 62 | 63 | com.sun.jersey 64 | jersey-json 65 | 1.4 66 | 67 | 68 | 69 | com.sun.jersey 70 | jersey-server 71 | 1.4 72 | 73 | 74 | 75 | org.springframework.boot 76 | spring-boot-starter-security 77 | 78 | 79 | 80 | io.jsonwebtoken 81 | jjwt 82 | 0.9.1 83 | 84 | 85 | 86 | 87 | book-rest-api 88 | 89 | 90 | org.springframework.boot 91 | spring-boot-maven-plugin 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /src/main/java/com/mightyjava/resource/impl/BookResourceImpl.java: -------------------------------------------------------------------------------- 1 | package com.mightyjava.resource.impl; 2 | 3 | import java.util.Collection; 4 | import java.util.Optional; 5 | 6 | import org.codehaus.jettison.json.JSONException; 7 | import org.codehaus.jettison.json.JSONObject; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.http.HttpStatus; 12 | import org.springframework.http.ResponseEntity; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.RestController; 15 | 16 | import com.mightyjava.domain.Book; 17 | import com.mightyjava.exception.ApplicationException; 18 | import com.mightyjava.exception.BookNotFoundException; 19 | import com.mightyjava.resource.Resource; 20 | import com.mightyjava.service.IService; 21 | 22 | @RestController 23 | @RequestMapping("/books") 24 | public class BookResourceImpl implements Resource { 25 | 26 | private static Logger log = LoggerFactory.getLogger(BookResourceImpl.class); 27 | 28 | @Autowired 29 | private IService bookService; 30 | 31 | @Override 32 | public ResponseEntity> findAll() { 33 | log.info("BookResourceImpl - findAll"); 34 | return new ResponseEntity<>(bookService.findAll(), HttpStatus.OK); 35 | } 36 | 37 | @Override 38 | public ResponseEntity findById(Long id) { 39 | log.info("BookResourceImpl - findById"); 40 | Optional book = bookService.findById(id); 41 | if(!book.isPresent()) { 42 | throw new BookNotFoundException("Book not found"); 43 | } 44 | return new ResponseEntity<>(book.get(), HttpStatus.OK); 45 | } 46 | 47 | @Override 48 | public ResponseEntity save(Book book) { 49 | log.info("BookResourceImpl - save"); 50 | if(book.getId() != null) { 51 | throw new ApplicationException("Book ID found, ID is not required for save the data"); 52 | } 53 | return new ResponseEntity<>(bookService.saveOrUpdate(book), HttpStatus.CREATED); 54 | } 55 | 56 | @Override 57 | public ResponseEntity update(Book book) { 58 | log.info("BookResourceImpl - update"); 59 | if(book.getId() == null) { 60 | throw new ApplicationException("Book ID not found, ID is required for update the data"); 61 | } 62 | return new ResponseEntity<>(bookService.saveOrUpdate(book), HttpStatus.OK); 63 | } 64 | 65 | @Override 66 | public ResponseEntity deleteById(Long id) { 67 | log.info("BookResourceImpl - deleteById"); 68 | Optional book = bookService.findById(id); 69 | if(!book.isPresent()) { 70 | throw new BookNotFoundException("Book not found"); 71 | } 72 | return new ResponseEntity<>(bookService.deleteById(id), HttpStatus.OK); 73 | } 74 | 75 | @Override 76 | public ResponseEntity invalid() { 77 | log.info("BookResourceImpl - invalid"); 78 | JSONObject jsonObject = new JSONObject(); 79 | try { 80 | jsonObject.put("message", "something is missing, please check everything before sending the request!!!"); 81 | } catch (JSONException e) { 82 | e.printStackTrace(); 83 | } 84 | return new ResponseEntity<>(jsonObject.toString(), HttpStatus.OK); 85 | } 86 | 87 | } 88 | --------------------------------------------------------------------------------