Thursday 25 March 2021

@Transaction management internals (Proxy pattern)

How exactly @Transaction works:

Earlier we used to start, close, rollback the transactions programmatically. But with the introduction of @Transaction annotation life became easy. All the underlying transaction management will he handled by the framework.

@Service

public class EmployeeService {

        @Transactional

    public void saveEmployee (Employee employee){

        dao.saveEmployee (employee);

    }

}

The underlying  transaction managers handle the transaction, whichever is used, for example: HibernateTransactionManager or JpaTransactionManager


Internally Spring creates a Proxy for the EmloyeeService class. This proxy class is the one which handles the transaction management related activates, including exception handling and rollback of the transaction








Java interface - Diamond Problem

 public interface InterfaceEx {


default void name(){} //default method
static void name6(){}
}

interface InterfaceEx1{
default void name(){} // default method
static void name6(){}
}

//If a class is implementing 2 or more interfaces, with same method signature, compiler enforces class to Override that method.
//This is how diamond problem is resolved.
class ClassEx implements InterfaceEx, InterfaceEx1{ //

@Override
public void name() {

}
}

Tuesday 23 March 2021

Spring AOP example

 import com.fasterxml.jackson.databind.ObjectMapper;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class ControllerAOP {

//execution command : <access specifier> <return type> <pacakge.classname.methodname(returntype)>
//example: execution(* com.some.packagename.ClassName.methodname(allarguments))
@Pointcut(value = "execution(public * com.api.*.*.*(..))")
public void controllerPointCut() {}

//A pointcut on a annotation. example: to pointcut on 'Service' annotation
@Pointcut("@within(org.springframework.stereotype.Service)")
public void serviceAnnotationPointCut() {}

@Around(value = "controllerPointCut()")
public Object myAround(ProceedingJoinPoint jp) throws Throwable {

ObjectMapper objectMapper = new ObjectMapper();

System.out.println("Method name :" + jp.getSignature().getName()); // to get method name
System.out.println("Class name : " + jp.getTarget().getClass().getName()); // to get class name
System.out.println("Arguments : " + objectMapper.writeValueAsString(jp.getArgs())); //to get arguments

Object obj = jp.proceed();

System.out.println("Response : " + objectMapper.writeValueAsString(obj)); //to get response body

return obj;
}

@Around(value = "serviceAnnotationPointCut()")
public Object serviceAnnotationAround(ProceedingJoinPoint jp) throws Throwable {

ObjectMapper objectMapper = new ObjectMapper();

System.out.println("Method name :" + jp.getSignature().getName()); // to get method name
System.out.println("Class name : " + jp.getTarget().getClass().getName()); // to get class name
System.out.println("Arguments : " + objectMapper.writeValueAsString(jp.getArgs())); //to get arguments

Object obj = jp.proceed();

System.out.println("Response : " + objectMapper.writeValueAsString(obj)); //to get response body

return obj;
}

}

Friday 19 March 2021

resilience4j circuitBreaker lifecycle

  CircuitBreaker comes up with three default states: CLOSED, OPEN and HALF_OPEN

 CLOSED : Everything is normal. All requests and responses are passed

 OPEN : CB opens if the configured number of failure is matched

 HALF_OPEN : CB waits till the duration we configure, then again it tries to CLOSE the CB by few more configured attempts. It fails again, CB goes back to CLOSE state. CB doesn't go back to CLOSED state until HALF_OPEN attempts are passed.

 

Below are the sample CB configurations:


ringBufferSizeInClosedState: 5  // CB is kept closed until 5 consecutive fail attempts. Then CB moves to OPEN state after 5 consecutive failures

waitDurationInOpenState: 10s // CB waits for 10 seconds in HALF_OPEN state

ringBufferSizeInHalfOpenState: 2 // CB tries 2 attempts being in HALF_OPEN state, within these 2 attempts if CB is passed, CB moves to CLOSED state. If it fails, CB moves back to OPEN state.