AOP is a programming paradigm that allows us to separate business logic from some technical code that crosscuts all application
Log is a big important element of all applications, because it permit developers to analysis fail and behaviors of the applications. A good log promote a faster analysis and a faster solutions to fail and bad behaviors.
When a developer will develop an application using oriented object programming (OOP), he think about how he can separate and distribute logics and responsibility to classes and how he can separate the bussiness logic from remaining. However, when we think about logs, promote this separation is not an easy task, because log is a concern that crosscut all application. With this, the Aspect-Oriented Programming (AOP) is a good tool to resolve that and promote this separation. In my book I said that, “AOP is a programming paradigm that allows us to separate business logic from some technical code that crosscuts all application“. In this post I will not explain about AOP, but I’ll show you how to use AOP to separate the log logic from business logic using CDI Interceptor. If you can know more about look my book.
First of all, we need define the exceptions that need by logged as error. For example, if the application throw a business exception, probably you don’t need log as a error, because it will grow up us log and exception is not a application fail or bad behaviors, but is an error of the user. However, a business exception need be logged as debug. Lets go to code…
First we need create a qualifier. In this example we created a qualifier called Logger.
@Inherited @InterceptorBinding @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.TYPE}) public @interface Logger { }
Now, we’ll create the CDI Interceptor that will intercept the calls and treat the log.
import org.apache.logging.log4j.LogManager; import javax.interceptor.AroundInvoke; import javax.interceptor.Interceptor; import javax.interceptor.InvocationContext; import java.io.Serializable; @Interceptor @Logger public class LoggerInterceptor implements Serializable { @AroundInvoke public Object proccessMethod(InvocationContext context) throws Exception { org.apache.logging.log4j.Logger logger = LogManager.getLogger(context.getTarget().getClass()); try { logger.debug("Called: " + context.getMethod()); return context.proceed(); } catch(Exception e){ treatException(e, context); throw e; } } private void treatException(Exception e, InvocationContext context){ org.apache.logging.log4j.Logger logger = LogManager.getLogger(context.getTarget().getClass()); if( !(e instanceof BusinessException)) { logger.error(e); } else{ logger.debug("Business Logic", e); } }
Note that, on treatException method, we log the BusinessException as debug. Furthermore, we do a log and throw the exception again. It is considered a bad practice, but in our example is not a bad practice, because the logic of logger is separated from business logic, with this the business logic need receive the exception to apply some treatment.
Now, we’ll configure our the business logic class to be intercepted by our LoggerInterceptor class. We will do that using the qualifier Logger
@Stateless @Logger public class MyBusiness { ... }
We used the interceptor to intercept a EJB class, but we can use with any class managed by Java EE context.
As the last step, you need configure the Interceptor on the beans.xml file.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" bean-discovery-mode="all"> <interceptors> <class>net.rhuanrocha.logger.LoggerInterceptor</class> </interceptors> </beans>
If you want to know more about AOP get my book in this link:
https://www.packtpub.com/application-development/java-ee-8-design-patterns-and-best-practices
Leave a Reply