Sunday, 25 February 2018

How to auto start Spring application after modifying the files ?


Add dependency in pom.xml of the application.
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>


It will enable auto-start of the web application, when we modify any file during development.

How to use controllers in a Spring web project ?


Make sure you have added dependency for a Web application
        <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
        </dependency>


EXAMPLE 1
Create a class with @Component and @RequestMapping annotations to indicating the path.
Use @GetMapping to serve by HTTP GET request and @ResponseBody to return response body with controller method.

@Component
@RequestMapping("hello")

public class EmpController {

   
    @GetMapping
    @ResponseBody

    public String hello() {
        return "Hello world";
    }

}

To access above controller, use : http://localhost:8080/hello
Since there is a single method defined with @GetMapping and @ResponseBody , it will be called.


EXAMPLE 2
@Component
@RequestMapping("hello")

public class EmpController2 {
   
    @GetMapping("rest")
    @ResponseBody

    public String hello() {
        return "hello";
    }

}

Here, we provided another path with the method also using @GetMapping("path")
To access above controller method, use http://localhost:8080/hello/rest


EXAMPLE 3
Instead of using @GetMapping, @PostMapping etc., you can use @RequestMapping by specifying path and method attributes.

@Component
@RequestMapping("hello")

public class EmpController2 {

   
    @RequestMapping(path="rest2", method=RequestMethod.GET)
    @ResponseBody

    public String hello2() {
        return "hello 2";
    }

}


You can access above method using : http://localhost:8080/hello/rest2

EXAMPLE 4
When you need a HTML page, instead of text from the controller method, DO NOT use @responseBody annotation and return a ModelAndView object.

@Component
@RequestMapping("hello")

public class EmpController2 {

    @GetMapping("html")
    public ModelAndView helloPg() {
        ModelAndView modelAndView = new ModelAndView("hello");
        modelAndView.addObject("name", "SHAAN");
        return modelAndView;
    }

}

You can access above method using : http://localhost:8080/hello/html
It will search and display : /src/main/resources/templates/hello.html

Wednesday, 21 February 2018

What is the usage and how to use the Interceptors ?


Interceptor can be used to avoid repetitive handler code (parameter change, logging etc.)

DispatcherServlet uses HandlerAdaptor to invoke the method.
HandlerInterceptor can perform action :
  • before handling
  • after handling
  • after completion (on rendering the view)

CREATING INTERCEPTOR
1. implement HandlerInterceptor interface
have to implement all 3 methods : prehandle() , postHandle(), afterCompletion()
OR
2. extend HandlerInterceptorAdapter class
have to implement only 1 method : prehandle()


@Configuration
public class MyInterceptor extends HandlerInterceptorAdapter {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
        System.out.println("Inside Interceptor - preHandle() ...");

        // You can access and manipulate the request and response objects here ...
        return true;
    }
}



REGISTERING INTERCEPTOR
1. Extend the main class with WebMvcConfigurerAdapter class.
2. Override the method addInterceptors and register all the interceptors in registry object.

@SpringBootApplication
public class TrainingApplication extends WebMvcConfigurerAdapter {

    @Resource
    private MyInterceptor myInterceptor;
   
    public static void main(String[] args) {
        ConfigurableApplicationContext ctx = SpringApplication.run(TrainingApplication.class, args);
    }
   
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor).addPathPatterns("/emp");
    }
}



When you request using the defined pattern (Example : http://localhost:8080/emp), this interceptor will be called.
If you do not add any addPathPatterns method call, interceptor will be called for each path.


Wednesday, 14 February 2018

How to implement AOP in Spring using annotations ?


CONCEPTS
Aspect : Implementation of cross cutting concern. Like, Txn mgt, Logging
Joinpoints : Point during program execution. Like, Method execution, Throw of exception
Advice : Action by Aspect at a particular Joinpoint.
Pointcut : Predicate to match Joinpoints. Advice is associated with a Pointcut expression.
AOP Proxy : Object created by AOP framework to implement Aspect contract.


PACKAGE STRUCTURE FOR AOP
  • Main app : com.org.TrainingApplication
  • Aspect : Use subpackage to keep the aspects - com.org.aspect.TrainingApplication
  • Aspect : Use another subpackage to keep the beans - com.org.training.A, B, C ...

Annotations on class
  • Use @Aspect to indicate the class managing the Cross cutting concern.
  • As usual, @Component is required to manage it by Spring container.

Annotations on methods
  • Use @Pointcut using pattern expression to indicate where to apply the advice.
    • pattern indicating the packages, classes, methods and arguments.
    • Provide packages, where you do not have your Application class as well 
  • Use different Advice annotations to provide actions to be taken and map with triggering events. Each of advice maps with one or many pointcut to know where to apply the advice.
    • @Before : Runs before actual method. JoinPoint object can be used to fetch method input metadata
    • @After : Runs before actual method. ProceedingJoinPoint object can be used to fetch output metadata
    • @Around : Wraps the actual method. Implementation for both (Before and After) can be provided before or after proceed() method of ProceedingJoinPoint.
    • @AfterThrowing : Runs when actual method throws exception. JoinPoint object can be used to fetch method metadata. 


@Component
@Aspect

public class Logging {
    // Pointcut for all classes & methods in package and subpackages under com.orange.training
    @Pointcut("execution(public * com.orange.training..*(..))")
    public void allMethods() {
       
    }   


     // Pointcut for all classes & methods with name starting "get" in package and subpackages under com.orange.training
     @Pointcut("execution(public * com.orange.training..*.get*(..))")
    public void restrictGetters() {
       
    }
 

    // Advice called before methods indicated in pointcuts
    @Before("allMethods() && !restrictGetters()")
    public void log() {
        System.out.println("Begining of method !!!");
    }



    // Advice called before methods indicated in pointcut
    @Before("allMethods()")
    public void log(JoinPoint jp) {
        System.out.println("Begining of method before : " + jp.getSignature());
    }
    

   
    // Advice called before and after method calls indicated in pointcut 
    // (Code before/after proceed method)
    @Around("allMethods()")
    public Object log(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("Begining of method around : " + pjp.getSignature());
        Object result = pjp.proceed();
        System.out.println(result);

        return result;
    }
    


    // Advice called after an exception is thrown in the methods indicated in pointcut        

    @AfterThrowing(pointcut="allMethods()", throwing="ex")
    public void log(JoinPoint pjp, Exception ex) {
        System.out.println("Begining of method throw : " + pjp.getSignature());
        System.out.println(ex);
    }
}


Thursday, 8 February 2018

How to use multiple properties file ?


Use any file and put it parallel to application.properties.

application.properties uses its values, but if there are some other file to be used, pass JVM argument : -Dspring.profiles.active={profile}

 -Dspring.profiles.active=dev

It will pick properties from application-dev.properties.


ORDER OF PICKING PROPERTIES
  • Profile specific application-{profile}.properties outside JAR
  • Profile specific application-{profile}.properties inside JAR
  • Profile specific application.properties outside JAR
  • Profile specific application.properties inside JAR

How to inject properties and data using annotations ?


Use @Value annotation

@Value("Hello")
private String greeting1;
   
@Value("${greeting}")
private String greeting2;


public void draw() {
        System.out.println(greeting1 + " | " + greeting2);

}

Provide your messages in application.properties
greeting=Bonjour

If you have same property in 2 different files, application.properties will override the value.


You can also use Environment, to get the message.
Useful when any message is used once only in the code.
@Autowired
Environment env;

public void draw() {
        System.out.println(env.getProperty("greeting"));

}



NESTED MESSAGES (in application.properties)

app=MyApp
greeting=Hello ${app}


SYSTEM PROPERTIES

ver=${java.version}

How to use BeanPostProcessor ?


Rarely used.
Can be used to see the logs of bean loading, dependency resolution etc. or to get more control with customization.
It is generic and will be called for all the beans.

Make a generic service class by implementing BeanPostProcessor interface and override its 2 methods.

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

  @Override
  public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
        System.out.println("postProcessAfterInitialization : " + name);
        return bean;

  }

  @Override
  public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
        System.out.println("postProcessBeforeInitialization : " + name);
        return bean;
    }   
}



Going one step further, we can use another interface BeanFactoryPostProcessor to provide the Abstract factory implementation for your post processor.
Normally, very rarely used.

Implements BeanFactoryPostProcessor interface and override its 1 method.

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
        factory.addBeanPostProcessor(new MyBeanPostProcessor());
    }
}


How to use life cycle of beans using annotations ?


You can use annotations :
@PostConstruct : called after bean is initialize
@PreDestroy : called before bean will destroy


@Autowired 
private Shape line;

static {
  ....
}

{
  ....
}

// Constructor
public Drawing() {
        System.out.println("Object of line in constructor : " + line);

}

@PostConstruct
private void init() {
        System.out.println("Initializing ***");

        System.out.println("Object of line in callback init : " + line);
}


@PreDestroy
private void destroy() {
        System.out.println("Destroying ***");
}


Inside constructor, you will get null for line object because the dependencies are not resolved in constructor.

ORDER : static block -> block -> constructor -> Spring callback

We have other alternatives like, implements InitializingBean, DIsposableBean of Spring.
But preferred are the above annotations because they exists in javax (JEE) - Framework independent.



Wednesday, 7 February 2018

How to use Autowiring using annotations ?



CLASS DEFINITIONS
// base class
public abstract class Shape {
    abstract void draw();
}



@Component
public class Arc extends Shape {
    public void draw() {
        System.out.println("Draw an Arc...");
    }
}


@Component
public class Line extends Shape {
    public void draw() {
        System.out.println("Draw a Line...");
    }

}



@Component
public class Drawing {
    @Autowired
    private Shape arc;

    // Check ByType first, since there is 2 implementation of Shape => arc & line, Then
       It will check ByName and it will find it => Arc class name

    @Autowired
   
private Shape arc1;
    // Check ByType first, since there is 2 implementation of Shape => arc & line, Then
       It will check ByName. It will not find any class arc1 and throw error when creating this bean
    @Autowired
    private Shape line;
    
// Check ByType first, since there is 2 implementation of Shape => arc & line, Then
       It will check ByName and it will find it => Arc class name

    public void drawAll() {
        arc.draw();
        arc1.draw();
        line.draw();
    }
}


// USAGE
ConfigurableApplicationContext ctx = SpringApplication.run(TrainingApplication.class, args);
Drawing drawing = ctx.getBean(Drawing.class);
drawing.drawAll();



USING @Qualifier
You can use @Qualifier annotation to specify the Bean name to inject explicitly.
    @Qualifier("arc")
    @Autowired

    private Shape arc1;
    // It will consult @Qualifier to check the bean name and autowire it ByName



USING @Resource
@Resource can be used in place of @Autowired and @Qualifier (2 annotations)   
    @Resource("name=arc")
    private Shape arc1;
    // Using @Resource, it checks ByType, since there is 2 implementation of Shape => arc & line,
       Then it will consult name given with @Resource and autowire it ByName


Autowired vs. Resource annotation


Best practice is to use @Resource instead of @Autowired because :
1. @Resource is defined in javax (JEE) while @Autowired is part of Spring APIs.
    So, preferred to use Framework independent annotation which will not change, 
    when framework needs to be changed.

2. @Resource can be used in place of 2 annotations : @Qualifier and @Autowired

   
    @Qualifier("arc")
    @Autowired
    private Shape arc1;

    SAME AS :

    @Resource("name=arc")
    private Shape arc1;