Jakarta CDI - After Intermediate Lab 2
In this lab, we will explore the CDI interceptor, creating a timer for methods.
1. Create a Timed annotation
- Create a new package called
auditedin theexpert.os.labs.persistence.cidpackage - Create an interface called
Timedin theexpert.os.labs.persistence.cid.auditedpackage - Annotate the interface as
@interface - Add the following annotations:
@InterceptorBindingfrom thejakarta.interceptorpackage@Target({METHOD, TYPE})- the
@Targetis from thejava.lang.annotationpackage - the
METHODandTYPEis from thejava.lang.annotation.ElementTypepackage
- the
@Retention(RUNTIME)- the
@Retentionis from thejava.lang.annotationpackage - the
RUNTIMEis from thejava.lang.annotation.ElementTypepackage
- the
Solution
Click to see...
import jakarta.interceptor.InterceptorBinding;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@InterceptorBinding
@Target({METHOD, TYPE})
@Retention(RUNTIME)
public @interface Timed {
}
2. Create the TimedInterceptor Class
Steps
- Create a class called
TimedInterceptorin theexpert.os.labs.persistence.cid.auditedpackage - Add the following annotations:
@Timed@Interceptorfrom thejakarta.interceptorpackage@Priority(Interceptor.Priority.APPLICATION)from thejakarta.annotationpackage- the
Interceptoris from thejakarta.interceptorpackage
- the
- Define a private attribute
Loggerfrom thejava.util.loggingpackage - Create a method called
timerthat will return anObject- it has a parameter
InvocationContextfrom thejakarta.interceptorpackage
- it has a parameter
- Annotate the method with
@AroundInvokefrom thejakarta.interceptorpackage - In the
timer()method, add:- the current time into a variable using the
System.currentTimeMillis() - the next interceptor using
ctx.proceed();, associating it to an object - the time slapsed into a variale (
System.currentTimeMillis() - start) - the information about the time slapsed into a
Stringshowing it usingctx.getTarget().getClass(), ctx.getMethod(), end - Log the content of the information using the logger
- return the information
- the current time into a variable using the
Solution
Click to see...
import jakarta.annotation.Priority;
import jakarta.interceptor.AroundInvoke;
import jakarta.interceptor.Interceptor;
import jakarta.interceptor.InvocationContext;
import java.util.logging.Logger;
@Timed
@Interceptor
@Priority(Interceptor.Priority.APPLICATION)
public class TimedInterceptor {
private static final Logger LOGGER = Logger.getLogger(TimedInterceptor.class.getName());
@AroundInvoke
public Object timer(InvocationContext ctx) throws Exception {
long start = System.currentTimeMillis();
Object result = ctx.proceed();
long end = System.currentTimeMillis() - start;
String message = String.format("Time to execute the class %s, the method %s is %d milliseconds",
ctx.getTarget().getClass(), ctx.getMethod(), end);
LOGGER.info(message);
return result;
}
}
3. Create the FastSupplier Class
Steps
- Create a class
FastSupplierin the in theexpert.os.labs.persistence.cid.auditedpackage - Implement the
Supplier<String> - Annotate the method
get()with@Timed - Return any
String
Solution
Click to see...
4. Create the SlowSupplier Class
Steps
- Create a class
SlowSupplierin the in theexpert.os.labs.persistence.cid.auditedpackage - Implement the
Supplier<String> - Annotate the method
get()with@Timed -
Add the following code to the method
Solution
Click to see...
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
public class SlowSupplier implements Supplier<String> {
@Timed
@Override
public String get() {
try {
TimeUnit.MILLISECONDS.sleep(200L);
} catch (InterruptedException e) {
//TODO it is only a sample, don't do it on production :)
throw new RuntimeException(e);
}
return "The slow result";
}
}
5. Create the app class
Steps
- Create a class called
AppInterceptorin theexpert.os.labs.persistence.cidpackage -
Add a main method
-
Set up a try-with-resources block, inside the
mainmethod, to manage the Jakarta EESeContainerthat is responsible for dependency injection and managing resources -
Obtain the value of the
FastSupplierthrough the container instance - Obtain the value of the
SlowSupplierthrough the container instance - Printout both results
Expected results
-
The following output
INFO: Time to execute the class class expert.os.labs.persistence.cdi.audited.FastSupplier$Proxy$_$$_WeldSubclass, the method public java.lang.String expert.os.labs.persistence.cdi.audited.FastSupplier.get() is 0 milliseconds The result: The Fast supplier result INFO: Time to execute the class class expert.os.labs.persistence.cdi.audited.SlowSupplier$Proxy$_$$_WeldSubclass, the method public java.lang. String expert.os.labs.persistence.cdi.audited.SlowSupplier.get() is 203 milliseconds The result: The slow result
Solution
Click to see...
import expert.os.labs.persistence.cdi.audited.FastSupplier;
import expert.os.labs.persistence.cdi.audited.SlowSupplier;
import jakarta.enterprise.inject.se.SeContainer;
import jakarta.enterprise.inject.se.SeContainerInitializer;
import java.util.function.Supplier;
public class AppInterceptor {
public static void main(String[] args) {
try (SeContainer container = SeContainerInitializer.newInstance().initialize()) {
Supplier<String> fastSupplier = container.select(FastSupplier.class).get();
Supplier<String> slowSupplier = container.select(SlowSupplier.class).get();
System.out.println("The result: " + fastSupplier.get());
System.out.println("The result: " + slowSupplier.get());
}
}
}