Difference between revisions of "SpringBoot"

(Created page with "==What is springboot?==")
 
(application.properties)
 
(29 intermediate revisions by the same user not shown)
Line 1: Line 1:
==What is springboot?==
+
'''How to test private method?'''
 +
If you have somewhat of a legacy Java application, and you're not allowed to change the visibility of your methods, '''the best way to test private methods is to use reflection'''.
 +
<source>
 +
Method method = targetClass.getDeclaredMethod(methodName, argClasses);
 +
method.setAccessible(true);
 +
return method.invoke(targetObject, argObjects);
 +
</source>
 +
And for fields:
 +
<source>
 +
Field field = targetClass.getDeclaredField(fieldName);
 +
field.setAccessible(true);
 +
field.set(object, value);
 +
</source>
 +
 
 +
Official Reference Book : https://docs.spring.io/spring-boot/docs/current/reference/pdf/spring-boot-reference.pdf
 +
 
 +
==application.properties==
 +
<source>
 +
server.port=8080
 +
</source>
 +
Other properties :
 +
https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html
 +
 
 +
==SpringBoot - Maven - Pom.xml==
 +
 
 +
<syntaxhighlight lang="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.oasissoftech.springboot</groupId>
 +
<artifactId>SpringBoot-Tutorial-1</artifactId>
 +
<version>0.0.1-SNAPSHOT</version>
 +
<name>SpringBoot-Tutorial-1</name>
 +
 
 +
<parent>
 +
<groupId>org.springframework.boot</groupId>
 +
<artifactId>spring-boot-starter-parent</artifactId>
 +
<version>2.0.2.RELEASE</version>
 +
</parent>
 +
 
 +
<dependencies>
 +
<dependency>
 +
<groupId>org.springframework.boot</groupId>
 +
<artifactId>spring-boot-starter-web</artifactId>
 +
</dependency>
 +
</dependencies>
 +
 
 +
<properties>
 +
<java.version>1.8</java.version>
 +
</properties>
 +
 
 +
</project>
 +
 
 +
</syntaxhighlight>
 +
 
 +
to get latest Spring Boot Starter Parent pom.xml configurations visit : [https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent]
 +
 
 +
to get latest Spring Boot Web Starter pom.xml configurations visit : [https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web]
 +
 
 +
 
 +
==SpringBoot - Application Boot==
 +
Spring Boot application startup class :
 +
 
 +
<syntaxhighlight lang="java">
 +
package com.oasissofttech.springboot;
 +
 
 +
import org.springframework.boot.SpringApplication;
 +
import org.springframework.boot.autoconfigure.SpringBootApplication;
 +
 
 +
@SpringBootApplication
 +
public class SpringBootTutorial1App {
 +
public static void main(String[] args) {
 +
SpringApplication.run(SpringBootTutorial1App.class,args);
 +
}
 +
}
 +
</syntaxhighlight>
 +
 
 +
 
 +
==SpringBoot - Controller Class - GET, POST, PUT, DELETE==
 +
 
 +
<syntaxhighlight lang="java">
 +
package com.oasissofttech.springboot.brand;
 +
 
 +
import java.util.List;
 +
 
 +
import org.springframework.beans.factory.annotation.Autowired;
 +
import org.springframework.web.bind.annotation.PathVariable;
 +
import org.springframework.web.bind.annotation.RequestBody;
 +
import org.springframework.web.bind.annotation.RequestMapping;
 +
import org.springframework.web.bind.annotation.RequestMethod;
 +
import org.springframework.web.bind.annotation.RestController;
 +
 
 +
@RestController
 +
public class BrandController {
 +
@Autowired
 +
private BrandService brandService;
 +
 +
@RequestMapping("/brands")
 +
public List<Brand> getAllBrands() {
 +
return brandService.getAllBrands();
 +
}
 +
 +
@RequestMapping("/brand/{brandId}")
 +
public Brand getBrand(@PathVariable("brandId") int id) {
 +
return brandService.getBrand(id);
 +
 +
}
 +
 +
@RequestMapping(method=RequestMethod.POST,value="/brands")
 +
public void addBrand(@RequestBody Brand brand) {
 +
brandService.addBrand(brand);
 +
}
 +
 +
@RequestMapping(method=RequestMethod.PUT,value="/brands/{id}")
 +
public void addBrand(@RequestBody Brand brand,@PathVariable int id) {
 +
brandService.updateBrand(brand,id);
 +
}
 +
 +
@RequestMapping(method=RequestMethod.DELETE,value="/brands/{id}")
 +
public void deleteBrand(@PathVariable int id) {
 +
brandService.deleteBrand(id);
 +
}
 +
 +
}
 +
 
 +
</syntaxhighlight>
 +
 
 +
 
 +
==SpringBoot - Service Class==
 +
 
 +
<syntaxhighlight lang="java">
 +
package com.oasissofttech.springboot.brand;
 +
 
 +
import java.util.ArrayList;
 +
import java.util.Arrays;
 +
import java.util.List;
 +
 
 +
import org.springframework.stereotype.Service;
 +
 
 +
@Service
 +
public class BrandService {
 +
 
 +
private List<Brand> brands = new ArrayList<>(Arrays.asList(
 +
new Brand(1,"Aston Martin","(1913–present)"),
 +
new Brand(2,"Bentley","(1919–present)"),
 +
new Brand(3,"Jaguar Land Rover","(2013-present)"),
 +
new Brand(4,"Lotus","(1952–present)"),
 +
new Brand(5,"Rolls Royce","(1904–present)")
 +
));
 +
 +
public List<Brand> getAllBrands(){
 +
return brands;
 +
}
 +
 +
 +
public Brand getBrand(int id) {
 +
return brands.stream().filter(b->b.getId()==id).findFirst().get();
 +
}
 +
 
 +
 
 +
public void addBrand(Brand brand) {
 +
brands.add(brand);
 +
}
 +
 
 +
 
 +
public void updateBrand(Brand brand, int id) {
 +
int c = brands.size();
 +
for(int i=0;i<c;i++) {
 +
if(brands.get(i).getId()==id) {
 +
brands.set(i, brand);
 +
return;
 +
}
 +
}
 +
}
 +
 
 +
 
 +
public void deleteBrand(int id) {
 +
brands.removeIf(t->t.getId()==id);
 +
}
 +
 +
}
 +
 
 +
</syntaxhighlight>
 +
 
 +
==[[Spring Cloud]]==
 +
 
 +
==[[API Gateway]]==
 +
The API Gateway '''encapsulates the internal system architecture and provides an API''' that is tailored to each client. It might have other responsibilities such as '''authentication, monitoring, load balancing, caching, request shaping and management, and static response handling'''.
 +
 
 +
==[[Netflix]]==
 +
===[[Euroka]]===
 +
===[[Chaos Monkey]]===
 +
 
 +
==SpringBoot CLI==
 +
https://docs.spring.io/spring-boot/docs/current/reference/html/getting-started.html#getting-started-installing-the-cli
 +
 
 +
https://sdkman.io/
 +
 
 +
===[[SDKMan]] installation===
 +
 
 +
<source>
 +
$ curl -s "https://get.sdkman.io" | bash
 +
</source>
 +
 
 +
SpringBoot CLI Installation with SDKMAN!
 +
<source>
 +
$ sdk install springboot
 +
$ spring --version
 +
Spring Boot v2.3.0.RELEASE
 +
</source>
 +
 
 +
 
 +
 
 +
==Others==
 +
 
 +
<syntaxhighlight lang="java">
 +
package com.oasissofttech.springboot.brand;
 +
 
 +
public class Brand {
 +
private int id;
 +
private String brandName;
 +
private String description;
 +
 
 +
public Brand() {
 +
}
 +
 
 +
public Brand(int id, String brandName, String description) {
 +
super();
 +
this.id = id;
 +
this.brandName = brandName;
 +
this.description = description;
 +
}
 +
 
 +
 
 +
public int getId() {
 +
return id;
 +
}
 +
 
 +
public void setId(int id) {
 +
this.id = id;
 +
}
 +
 
 +
public String getBrandName() {
 +
return brandName;
 +
}
 +
 
 +
public void setBrandName(String brandName) {
 +
this.brandName = brandName;
 +
}
 +
 
 +
public String getDescription() {
 +
return description;
 +
}
 +
 
 +
public void setDescription(String description) {
 +
this.description = description;
 +
}
 +
 
 +
}
 +
 
 +
</syntaxhighlight>
 +
 
 +
===Common application properties===
 +
'''application.properties file'''
 +
<source>
 +
#===========================================
 +
#=== application.properties file content ===
 +
server.port=3000 #server HTTP port.
 +
#===================end=====================
 +
</source>
 +
 
 +
springboot properties file manual : [https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html]
 +
 
 +
== [[JPA - Java Persistance API]] ==
 +
 
 +
 
 +
===[[ORM - Object Relational Mapping]]===
 +
===[[Spring Data JPA]]===
 +
manual : https://docs.spring.io/spring-data/jpa/docs/current/reference/html/
 +
 
 +
====Features====
 +
*Sophisticated support to build repositories based on Spring and JPA
 +
*Support for Querydsl predicates and thus type-safe JPA queries
 +
*Transparent auditing of domain class
 +
*Pagination support, dynamic query execution, ability to integrate custom data access code
 +
*Validation of @Query annotated queries at bootstrap time
 +
*Support for XML based entity mapping
 +
*JavaConfig based repository configuration by introducing @EnableJpaRepositories.
 +
 
 +
====Gradle Dependencies====
 +
<source>
 +
dependencies {
 +
    compile 'org.springframework.data:spring-data-jpa:2.0.10.RELEASE'
 +
}repositories {
 +
    maven {
 +
        url 'https://repo.spring.io/libs-release'
 +
    }
 +
}
 +
</source>
 +
 
 +
 
 +
===Making CRUD Operation with Repository===
 +
 
 +
'''@Repository'''
 +
<syntaxhighlight lang="java">
 +
import java.util.List;
 +
 
 +
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 com.lse.library.model.Books;
 +
 
 +
@Repository
 +
public interface LseLibraryRepository extends CrudRepository<Books,Long> {
 +
//ID,ISBN_NO,SUBJECT,AUTHOR,TITLE
 +
    @Query(value="SELECT * FROM LSE_LIBRARY_BOOKS s where s.SHELF_NO = :shelfNo", nativeQuery = true)
 +
    List<Books> findBooksByShelfNo(@Param("shelfNo") String shelfNo);
 +
 
 +
    //LOCATION_NO
 +
    @Query(value="SELECT * FROM LSE_LIBRARY_BOOKS s where s.ISBN_NO = :IsbnNo", nativeQuery = true)
 +
    Books findLocationByIsbnNo(@Param("IsbnNo") String IsbnNo);
 +
 
 +
    //STACK_NO,SHELF_NO
 +
    @Query(value="SELECT * FROM LSE_LIBRARY_BOOKS s where s.SUBJECT like CONCAT('%',:subject,'%')", nativeQuery = true) 
 +
    List<Books> findStacksAndShelvesBySubject(@Param("subject") String subject);
 +
 
 +
    @Query(value="SELECT count(*) ID FROM LSE_LIBRARY_BOOKS s where s.SHELF_NO = :shelfNo", nativeQuery = true)
 +
    int findCountOfBooksByShelfNo(@Param("shelfNo") String shelfNo);
 +
 
 +
    //SHELF_NO
 +
    @Query(value="SELECT * FROM LSE_LIBRARY_BOOKS s where s.SUBJECT = :subject1 or s.SUBJECT = :subject2 ", nativeQuery = true) 
 +
    List<Books> findShelvesBySubjects(@Param("subject1") String subject1,@Param("subject2") String subject2);
 +
 
 +
    //SHELF_NO
 +
    @Query(value="SELECT * FROM LSE_LIBRARY_BOOKS s where s.SUBJECT = :subject", nativeQuery = true) 
 +
    List<Books> findShelvesByOneSubject(@Param("subject") String subject);
 +
 
 +
}
 +
 
 +
</syntaxhighlight>
 +
 
 +
 
 +
 
 +
 
 +
'''BrandRepository interface'''
 +
 
 +
<syntaxhighlight lang="java">
 +
package com.oasissofttech.springboot.brand;
 +
 
 +
import org.springframework.data.repository.CrudRepository;
 +
 
 +
@Repository
 +
public interface BrandRepository extends CrudRepository<Brand, Integer> {
 +
 
 +
}
 +
</syntaxhighlight>
 +
 
 +
 
 +
 
 +
'''BrandService Class'''
 +
<syntaxhighlight lang="java">
 +
package com.oasissofttech.springboot.brand;
 +
 
 +
import java.util.ArrayList;
 +
import java.util.Arrays;
 +
import java.util.List;
 +
import java.util.Optional;
 +
 
 +
import org.springframework.beans.factory.annotation.Autowired;
 +
import org.springframework.stereotype.Service;
 +
 
 +
@Service
 +
public class BrandService {
 +
@Autowired
 +
private BrandRepository brandRepository;
 +
 +
public List<Brand> getAllBrands(){
 +
List<Brand> brands = new ArrayList<>();
 +
brandRepository.findAll()
 +
.forEach(brands::add);
 +
 +
return brands;
 +
}
 +
 +
 +
public Optional<Brand> getBrand(int id) {
 +
return brandRepository.findById(id);
 +
}
 +
 
 +
 
 +
public void addBrand(Brand brand) {
 +
brandRepository.save(brand);
 +
}
 +
 
 +
 
 +
public void updateBrand(Brand brand, int id) {
 +
brandRepository.save(brand);
 +
}
 +
 
 +
 
 +
public void deleteBrand(int id) {
 +
brandRepository.deleteById(id);
 +
}
 +
 +
}
 +
</syntaxhighlight>
 +
 
 +
 
 +
===What is WireMock?===
 +
https://www.ontestautomation.com/getting-started-with-wiremock/
 +
 
 +
From the WireMock.org website: '''WireMock is a flexible library for stubbing and mocking web services'''. Unlike general purpose mocking tools it '''works by creating an actual HTTP server''' that '''your code under test can connect to as it would a real web service'''. '''It supports HTTP response stubbing''', '''request verification''', '''proxy/intercept''', '''record/playback of stubs''' and '''fault injection''', and '''can be used from within a unit test''' or '''deployed into a test environment'''. Although it’s written in Java, there’s also a JSON API so you can use it with pretty much any language out there.
 +
 
 +
==Error Handling for REST with Spring & SpringBoot==
 +
===Overview===
 +
'''Before Spring 3.2''', the two main approaches to handling exceptions in a Spring MVC application were: '''HandlerExceptionResolver''' or the '''@ExceptionHandler''' annotation. Both of these have some clear downsides.
 +
 
 +
After '''3.2''' we now have the new '''@ControllerAdvice''' annotation to address the limitations of the previous two solutions.
 +
 
 +
 
 +
All of these do have one thing in common – they deal with the '''[[separation of concerns]]''' very well. The app can throw exception normally to indicate a failure of some kind – exceptions which will then be handled separately.
 +
 
 +
===The Controller level @ExceptionHandler===
 +
====The New @ControllerAdvice (Spring 3.2 And Above)====
 +
Spring 3.2 brings support for a global @ExceptionHandler with the new @ControllerAdvice annotation. This enables a mechanism that breaks away from the older MVC model and makes use of ResponseEntity along with the type safety and flexibility of @ExceptionHandler:
 +
 
 +
<syntaxhighlight lang="java">
 +
@ControllerAdvice
 +
public class RestResponseEntityExceptionHandler
 +
  extends ResponseEntityExceptionHandler {
 +
 +
    @ExceptionHandler(value
 +
      = { IllegalArgumentException.class, IllegalStateException.class })
 +
    protected ResponseEntity<Object> handleConflict(
 +
      RuntimeException ex, WebRequest request) {
 +
        String bodyOfResponse = "This should be application specific";
 +
        return handleExceptionInternal(ex, bodyOfResponse,
 +
          new HttpHeaders(), HttpStatus.CONFLICT, request);
 +
    }
 +
}
 +
</syntaxhighlight>
 +
 
 +
The new annotation allows the multiple scattered @ExceptionHandler from before to be consolidated into a single, global error handling component.
 +
 
 +
The actual mechanism is extremely simple but also very flexible:
 +
*'''it allows full control over the body of the response as well as the status code'''
 +
*'''it allows mapping of several exceptions to the same method, to be handled together'''
 +
*'''it makes good use of the newer RESTful ResposeEntity response'''
 +
 
 +
One thing to keep in mind here is to match the exceptions declared with @ExceptionHandler with the exception used as the argument of the method. If these don’t match, the compiler will not complain – no reason it should, and Spring will not complain either.
 +
 
 +
However, when the exception is actually thrown at runtime, the exception resolving mechanism will fail with:
 +
 
 +
<syntaxhighlight lang="java">
 +
java.lang.IllegalStateException: No suitable resolver for argument [0] [type=...]
 +
HandlerMethod details: ...
 +
</syntaxhighlight>
 +
 
 +
 
 +
http://www.baeldung.com/exception-handling-for-rest-with-spring
 +
 
 +
==Spring Boot Interview Questions and Answers==
 +
*[[Spring Boot Interview Questions and Answers-1]] - http://www.javainuse.com/spring/SpringBootInterviewQuestions
 +
 
 +
*[[Spring Boot Interview Questions and Answers-2]] - http://www.springboottutorial.com/spring-boot-interview-questions
 +
 
 +
 
 +
===What is '''OAuth2'''? How to implement it using Spring Boot?===
 +
 
 +
Spring Boot + OAuth2 implementation : http://www.javainuse.com/spring/spring-boot-oauth-introduction
 +
 
 +
'''OAuth (Open Authorization)''' is a simple way to publish and interact with protected data.
 +
It is an open standard for token-based authentication and authorization on the Internet. It allows an end user's account information to be used by third-party services, such as Facebook, without exposing the user's password.
 +
 
 +
'''The OAuth specification describes five grants for acquiring an access token:'''
 +
*Authorization code grant
 +
*Implicit grant
 +
*Resource owner credentials grant
 +
*Client credentials grant
 +
*Refresh token grant

Latest revision as of 03:54, 17 May 2020

How to test private method? If you have somewhat of a legacy Java application, and you're not allowed to change the visibility of your methods, the best way to test private methods is to use reflection.

Method method = targetClass.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true);
return method.invoke(targetObject, argObjects);

And for fields:

Field field = targetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);

Official Reference Book : https://docs.spring.io/spring-boot/docs/current/reference/pdf/spring-boot-reference.pdf

application.properties

server.port=8080

Other properties : https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html

SpringBoot - Maven - 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.oasissoftech.springboot</groupId>
	<artifactId>SpringBoot-Tutorial-1</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>SpringBoot-Tutorial-1</name>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.2.RELEASE</version>
	</parent>

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

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

</project>

to get latest Spring Boot Starter Parent pom.xml configurations visit : https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent

to get latest Spring Boot Web Starter pom.xml configurations visit : https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web


SpringBoot - Application Boot

Spring Boot application startup class :

package com.oasissofttech.springboot;

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

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


SpringBoot - Controller Class - GET, POST, PUT, DELETE

package com.oasissofttech.springboot.brand;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class BrandController {
	@Autowired
	private BrandService brandService;
	
	@RequestMapping("/brands")
	public List<Brand> getAllBrands() {
		return brandService.getAllBrands();
	}
	
	@RequestMapping("/brand/{brandId}")
	public Brand getBrand(@PathVariable("brandId") int id) {
		return brandService.getBrand(id);
	
	}
	
	@RequestMapping(method=RequestMethod.POST,value="/brands")
	public void addBrand(@RequestBody Brand brand) {
		brandService.addBrand(brand);
	}
	
	@RequestMapping(method=RequestMethod.PUT,value="/brands/{id}")
	public void addBrand(@RequestBody Brand brand,@PathVariable int id) {
		brandService.updateBrand(brand,id);
	}
	
	@RequestMapping(method=RequestMethod.DELETE,value="/brands/{id}")
	public void deleteBrand(@PathVariable int id) {
		brandService.deleteBrand(id);
	}
	
}


SpringBoot - Service Class

package com.oasissofttech.springboot.brand;

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

import org.springframework.stereotype.Service;

@Service
public class BrandService {

	private List<Brand> brands = new ArrayList<>(Arrays.asList(
			new Brand(1,"Aston Martin","(1913–present)"),
			new Brand(2,"Bentley","(1919–present)"),
			new Brand(3,"Jaguar Land Rover","(2013-present)"),
			new Brand(4,"Lotus","(1952–present)"),
			new Brand(5,"Rolls Royce","(1904–present)")
			));
	
	public List<Brand> getAllBrands(){
		return brands;
	}
	
	
	public Brand getBrand(int id) {
		return brands.stream().filter(b->b.getId()==id).findFirst().get();
	}


	public void addBrand(Brand brand) {
		brands.add(brand);
	}


	public void updateBrand(Brand brand, int id) {
		int c = brands.size();
		for(int i=0;i<c;i++) {
			if(brands.get(i).getId()==id) {
				brands.set(i, brand);
				return;
			}
		}
	}


	public void deleteBrand(int id) {
		brands.removeIf(t->t.getId()==id);
	}
	
}

Spring Cloud

API Gateway

The API Gateway encapsulates the internal system architecture and provides an API that is tailored to each client. It might have other responsibilities such as authentication, monitoring, load balancing, caching, request shaping and management, and static response handling.

Netflix

Euroka

Chaos Monkey

SpringBoot CLI

https://docs.spring.io/spring-boot/docs/current/reference/html/getting-started.html#getting-started-installing-the-cli

https://sdkman.io/

SDKMan installation

$ curl -s "https://get.sdkman.io" | bash

SpringBoot CLI Installation with SDKMAN!

$ sdk install springboot
$ spring --version
Spring Boot v2.3.0.RELEASE


Others

package com.oasissofttech.springboot.brand;

public class Brand {
	private int id;
	private String brandName;
	private String description;

	public Brand() {
	}

	public Brand(int id, String brandName, String description) {
		super();
		this.id = id;
		this.brandName = brandName;
		this.description = description;
	}


	public int getId() {
		return id;
	}

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

	public String getBrandName() {
		return brandName;
	}

	public void setBrandName(String brandName) {
		this.brandName = brandName;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

}

Common application properties

application.properties file

#===========================================
#=== application.properties file content ===
server.port=3000 #server HTTP port.
#===================end=====================

springboot properties file manual : https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

JPA - Java Persistance API

ORM - Object Relational Mapping

Spring Data JPA

manual : https://docs.spring.io/spring-data/jpa/docs/current/reference/html/

Features

  • Sophisticated support to build repositories based on Spring and JPA
  • Support for Querydsl predicates and thus type-safe JPA queries
  • Transparent auditing of domain class
  • Pagination support, dynamic query execution, ability to integrate custom data access code
  • Validation of @Query annotated queries at bootstrap time
  • Support for XML based entity mapping
  • JavaConfig based repository configuration by introducing @EnableJpaRepositories.

Gradle Dependencies

dependencies {
    compile 'org.springframework.data:spring-data-jpa:2.0.10.RELEASE'
}repositories {
    maven {
        url 'https://repo.spring.io/libs-release'
    }
}


Making CRUD Operation with Repository

@Repository

import java.util.List;

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 com.lse.library.model.Books;

@Repository
public interface LseLibraryRepository extends CrudRepository<Books,Long> {
	//ID,ISBN_NO,SUBJECT,AUTHOR,TITLE
    @Query(value="SELECT * FROM LSE_LIBRARY_BOOKS s where s.SHELF_NO = :shelfNo", nativeQuery = true) 
    List<Books> findBooksByShelfNo(@Param("shelfNo") String shelfNo);

    //LOCATION_NO
    @Query(value="SELECT * FROM LSE_LIBRARY_BOOKS s where s.ISBN_NO = :IsbnNo", nativeQuery = true) 
    Books findLocationByIsbnNo(@Param("IsbnNo") String IsbnNo);

    //STACK_NO,SHELF_NO
    @Query(value="SELECT * FROM LSE_LIBRARY_BOOKS s where s.SUBJECT like CONCAT('%',:subject,'%')", nativeQuery = true)   
    List<Books> findStacksAndShelvesBySubject(@Param("subject") String subject);

    @Query(value="SELECT count(*) ID FROM LSE_LIBRARY_BOOKS s where s.SHELF_NO = :shelfNo", nativeQuery = true) 
    int findCountOfBooksByShelfNo(@Param("shelfNo") String shelfNo);

    //SHELF_NO
    @Query(value="SELECT * FROM LSE_LIBRARY_BOOKS s where s.SUBJECT = :subject1 or s.SUBJECT = :subject2 ", nativeQuery = true)   
    List<Books> findShelvesBySubjects(@Param("subject1") String subject1,@Param("subject2") String subject2);

    //SHELF_NO
    @Query(value="SELECT * FROM LSE_LIBRARY_BOOKS s where s.SUBJECT = :subject", nativeQuery = true)   
    List<Books> findShelvesByOneSubject(@Param("subject") String subject);

}



BrandRepository interface

package com.oasissofttech.springboot.brand;

import org.springframework.data.repository.CrudRepository;

@Repository
public interface BrandRepository extends CrudRepository<Brand, Integer> {

}


BrandService Class

package com.oasissofttech.springboot.brand;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

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

@Service
public class BrandService {
	@Autowired
	private BrandRepository brandRepository;
	
	public List<Brand> getAllBrands(){
		List<Brand> brands = new ArrayList<>();
		brandRepository.findAll()
		.forEach(brands::add);
		
		return brands;
	}
	
	
	public Optional<Brand> getBrand(int id) {
		return brandRepository.findById(id);
	}


	public void addBrand(Brand brand) {
		brandRepository.save(brand);
	}


	public void updateBrand(Brand brand, int id) {
		brandRepository.save(brand);
	}


	public void deleteBrand(int id) {
		brandRepository.deleteById(id);
	}
	
}


What is WireMock?

https://www.ontestautomation.com/getting-started-with-wiremock/

From the WireMock.org website: WireMock is a flexible library for stubbing and mocking web services. Unlike general purpose mocking tools it works by creating an actual HTTP server that your code under test can connect to as it would a real web service. It supports HTTP response stubbing, request verification, proxy/intercept, record/playback of stubs and fault injection, and can be used from within a unit test or deployed into a test environment. Although it’s written in Java, there’s also a JSON API so you can use it with pretty much any language out there.

Error Handling for REST with Spring & SpringBoot

Overview

Before Spring 3.2, the two main approaches to handling exceptions in a Spring MVC application were: HandlerExceptionResolver or the @ExceptionHandler annotation. Both of these have some clear downsides.

After 3.2 we now have the new @ControllerAdvice annotation to address the limitations of the previous two solutions.


All of these do have one thing in common – they deal with the separation of concerns very well. The app can throw exception normally to indicate a failure of some kind – exceptions which will then be handled separately.

The Controller level @ExceptionHandler

The New @ControllerAdvice (Spring 3.2 And Above)

Spring 3.2 brings support for a global @ExceptionHandler with the new @ControllerAdvice annotation. This enables a mechanism that breaks away from the older MVC model and makes use of ResponseEntity along with the type safety and flexibility of @ExceptionHandler:

@ControllerAdvice
public class RestResponseEntityExceptionHandler 
  extends ResponseEntityExceptionHandler {
 
    @ExceptionHandler(value 
      = { IllegalArgumentException.class, IllegalStateException.class })
    protected ResponseEntity<Object> handleConflict(
      RuntimeException ex, WebRequest request) {
        String bodyOfResponse = "This should be application specific";
        return handleExceptionInternal(ex, bodyOfResponse, 
          new HttpHeaders(), HttpStatus.CONFLICT, request);
    }
}

The new annotation allows the multiple scattered @ExceptionHandler from before to be consolidated into a single, global error handling component.

The actual mechanism is extremely simple but also very flexible:

  • it allows full control over the body of the response as well as the status code
  • it allows mapping of several exceptions to the same method, to be handled together
  • it makes good use of the newer RESTful ResposeEntity response

One thing to keep in mind here is to match the exceptions declared with @ExceptionHandler with the exception used as the argument of the method. If these don’t match, the compiler will not complain – no reason it should, and Spring will not complain either.

However, when the exception is actually thrown at runtime, the exception resolving mechanism will fail with:

java.lang.IllegalStateException: No suitable resolver for argument [0] [type=...]
HandlerMethod details: ...


http://www.baeldung.com/exception-handling-for-rest-with-spring

Spring Boot Interview Questions and Answers


What is OAuth2? How to implement it using Spring Boot?

Spring Boot + OAuth2 implementation : http://www.javainuse.com/spring/spring-boot-oauth-introduction

OAuth (Open Authorization) is a simple way to publish and interact with protected data. It is an open standard for token-based authentication and authorization on the Internet. It allows an end user's account information to be used by third-party services, such as Facebook, without exposing the user's password.

The OAuth specification describes five grants for acquiring an access token:

  • Authorization code grant
  • Implicit grant
  • Resource owner credentials grant
  • Client credentials grant
  • Refresh token grant