JfreeCharts is a third party open source api to generate api.
Below is the low level work flow
If we write exception handler into the controller then we can not re-use it . Then need to write again which will violate co-usability rule.
So, to avoid code duplication we can define global exception handler using @ControllerAdvice.
@ControllerAdvice:
--Its similar to pre-processor/filter.
--Pre process request to controller.
-- Preprocess responses to handle exception.
--Perfect for global exception handling.
let's refactor our previous exception handling code-
@ControllerAdvice
public class StudentRestHandlerException{
@ExceptionHandler
public ResponseEntity<StudentErrorResponse> handleException(StudentNotFound exc){
StudentErrorResponse errorResponse = new StudentErrorResponse();
errorResponse.setStatus(HttpStatus.Not_found.value());
errorResponse.setMessage(exc.getMessage());
errorResponse.setTimeStamp(System.currentTimeMillis());
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);// will return a json .jackson will convert the pojo to json .
}
What if the user request using character in request parameter without giving integer value . then server again will show an ugly message .so we should handle it . so lets create another exception handler ..
@ExceptionHandler
public ResponseEntity<StudentErrorResponse> handleException(Exception ex){
StudentErrorResponse errorResponse = new StudentErrorResponse();
errorResponse.setStatus(HttpStatus.BAD_REQUEST.value());
errorResponse.setMessage(exc.getMessage());
errorResponse.setTimeStamp(System.currentTimeMillis());
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}
}
When we call a rest service with bad end points then it will throw an exception what will show lots of ugly information from the server . So we can modify the exception information by developing our own custom exception.
lets see the practical example-
1. Creating our custom exception response pojo class that we want to sent back to the client.
public class StudentErrorResponse{
private int status;
private String message;
private long timestamp;
public StudentErrorResponse(int status,String message,long timeStamp){
this.status = status;
this.message = message;
this.timeStamp = timeStamp;
}
//Appropriate getter and setter for the properties
}
Now let's create our custom exception class.
public class StudentNotFound extends RuntimeException{
public StudentNotFound(String message,Throwable cause){
super(message,cause);
}
public StudentNotFound(String message){
super(message);
}
public StudentNotFound(String cause){
super(cause);
}
}
Now lets throws exception from our rest controller if student is not found,
@RestController
@RequestMapping("/api")
public class StudentRestController{
private List<Student> students ;
@PostConstruct //defining @PostConstruct will load data only once after class has been loaded .
public void loadData(){
students = new ArrayList<Student>();
students.add(new Student("lokman","hossain"));
students.add(new Student("sadia","muna"));
}
@GetMapping("/students")
public List<Student> getStudents(){
return students;
}
@GetMapping("/students/{studentId}")
public Student getStudent(@PathVariable int studentId){
if((studentId>students.size() )|| (studentId<0))
throw new StudentNotFound("Student not found with the given student id:"+studentId);
return students.get(studentId);
}
//Adding exception handler
@ExceptionHandler
public ResponseEntity<StudentErrorResponse> handleException(StudentNotFound exc){
StudentErrorResponse errorResponse = new StudentErrorResponse();
errorResponse.setStatus(HttpStatus.Not_found.value());
errorResponse.setMessage(exc.getMessage());
errorResponse.setTimeStamp(System.currentTimeMillis());
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);// will return a json .jackson will convert the pojo to json .
}
What if the user request using character in request parameter without giving integer value . then server again will show an ugly message .so we should handle it . so lets create another exception handler ..
@ExceptionHandler
public ResponseEntity<StudentErrorResponse> handleException(Exception ex){
StudentErrorResponse errorResponse = new StudentErrorResponse();
errorResponse.setStatus(HttpStatus.BAD_REQUEST.value());
errorResponse.setMessage(exc.getMessage());
errorResponse.setTimeStamp(System.currentTimeMillis());
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}
}
By default jackson use appropriate getter and setter method to bind data .
lets see and example ,
Json to pojo--
let's see a practical example-
we have a file containing a json object representing student . Then read json object from the file and convert it to student object.
.import java.io.File;
.import com.fasterxml.jackson.databind.ObjectMapper;
public class MainApp{
public static void main(String[] args){
ObjectMapper objectMapper = new ObjectMapper();
Student student = objectMapper.readValue(new File("sample.json"),Student.class);
}
}
In this example objectMapper will read value from sample.json file and convert that json object into student object using corresponding setter methods.
N.B:When we converting json to pojo it will call setter but in vice versa it will call getter .But what if the corresponding getter and setter are not found then it will throw exception . So how we can avoid some property if needed .Then we can use special annotation -
@JsonIgnoreProperties(ignoreUnknown=true)
public class Student{
private int id;//has setter and getter
private String firstName;//has setter and getter
private String lastName;
}
Data binding is the process of converting json to java pojo or java pojo to json .
spring uses jackson project for data binding .
-jackson is data binding API.
package: com.fasterxml.jackson.databind
Maven dependency:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
We need to store data using a key in property file .Then use @Value annotation over a variable which will hold that data .Then we should use another @PropertySource annotation is used to provide properties file into spring environment .
Ex:
Suppose we have a url in app.properties file as
external.service.url = http://helloworld.com/hello
Now we have a service class which will provide this url .
@Component
public class ExternalService{
@Value("${external.service.url}")
private String url;
public String getUrl(){
return url;
}
}
Now we want to load properties file while load the class, then
@Configuration
@ComponentScan
@PropertySource("classpath:app.properties")
public class SpringFrameworkProperties{
public void main(String[] args){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringFrameworkProperties.class);
ExternalService service= context.getBean(ExternalService.class);
System.out.println(service.getUrl());
}
}
We already know that if we use @Component annotation we can easily identify bean in the IOC container .Then why need to use these special annotation-
@Controller: In MVC pattern @Controller annotation used to define servlet to serve for a http request.
@Repository : @Repository is the special annotation for encapsulation storage, retrieval and search behavior on relational database . Their may be any exception while operating certain operation in database but some of them can be handled by using @Repositoy annotation.
@Service: @Service annotation is used to define business layer in spring .
Specifically annotations are categorized to apply logic on them . Using AOP we can provide special logic on the annotation .
Bean factory and Application context both are IOC container. But there some differences between them,
Bean factory: Bean factory provides basic management for bean and wiring of dependencies.
Application context: Application context is beanfactory++. Not only provides basic management and wiring of dependencies but also provides Spring AOP features. WebApplication context for web applications ,provides internationalizations.
It is recommends to use Application context in most of the enterprise Application development .
@PostConstruct: As soon as the bean is created and all the dependency is injected then @PostConstruct would be called.
@PreDestroy: As soon as the bean is removed from the container @Predestroy method is called. We can use where we need to release resources by the bean .
By default bean scope is singleton that means every time we get a bean from ioc container will give me the copy of a bean .so beans are the same object.
But if we want to get different beans every time from the ioc container we should use prototype .
To define a prototype bean we can use @Scope("prototype")/@ConfigurableBeanFactory.SCOP_PROTOTYPE
ex:
If there is multiple implementation of an interface then we need to specify which one's implementation will use. For that reason we need to specify @Primary in the implemented class or we can use autowired by name .But @Primary annotation have the highest precedence than autowired by name.
Another approach is we can use @Qualifier("name") over the name of the implement class .We then should use this @Qualifier("name") over the injected interface.
Suppose we have a controller ,which accepts the request and will response , but it depends on business layer.
@Controller
public class TodoController{
@Autowired
TodoBusinessService todoBusinessService;
}
TodoBusinessService depends to another dependency to fetch data from the database,
@Component
public class TodoBusinessService{
@Autowired
TodoDataService todoDataService;
}
now TodoDataService need to fire a query to fetch data from the database .So it depends on JdbcTemplate.
@Component
public class TodoDataService {
@Autowired
JdbcTemplate jdbcTemplate;
}
1.what are the bean:-we annotate classes with @Component to specify our bean.
2.What are the dependencies of a bean:-We can annotate with @Autowired to specify dependencies.
3.Where to search for bean:-That means in which package beans are available .
we can specify through @ComponentScan annotation.
In spring boot @SpringBootApplication annotation automatically scan for beans in the package and sub-packages in which package this annotation reside.
--Application context: Application context is the spring container where all the beans are managed .We get beans from application context.
To check what is happening in background-
we can put logger in application.properties file as follows-
looging.level.org.springframework=debug
Annotations are meta data about a class that will be processed by compiler at runtime or compile time.
Ex: when we override a method of parent class then always we see a @Override annotation that is processed at compile time . It actually inform compiler that we are overriding a method .Then compiler check the classes .
when we use annotation in spring ,the it will scan java classes for special annotation.
Automatically register bean to spring container based on annotations.
Ex:
@Component("person")
public class Person extend Human{
}
here spring will scan for component and register this class as bean to spring container .
Using the bean id "person" we can able to retrieve the bean from spring container.
Retrieve bean from spring container,
Person person = context.getBean("person",Person.class);
here context is the ApplicationContext which is spring container.
- Scope refers to the life cycle of a bean .
-How long does the bean will alive
-How the bean will share
-How many instances will created
By default bean scope is singleton.
Singleton: Spring container will create single instance .All request for the bean will return a shared reference for that bean.
-Prototype:Create new reference and return it .
Ans: Dependency means something that is dependent on something .When an object dependent on another object then that object is the dependent object. Ex: if we assume car is an object then tire ,door, machine is the dependent object of car. So, dependency injection means of injecting dependent object from object factory(Spring container) throw constructor/setter/autowiring .
Dependency can be injected throw -
1.Constructor injection
2.Setter injection
3.Autowiring.
--Create and manage object(IOC-Inversion of control)
--Inject object dependencies(Dependency injection)
--Spring container generically known as ApplicationContext
Ex:xml based
------Controller------------- @RestController @RequestMapping("/items") public class ItemController { private final ItemServic...