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
audited
in theexpert.os.labs.persistence.cid
package - Create an interface called
Timed
in theexpert.os.labs.persistence.cid.audited
package - Annotate the interface as
@interface
- Add the following annotations:
@InterceptorBinding
from thejakarta.interceptor
package@Target({METHOD, TYPE})
- the
@Target
is from thejava.lang.annotation
package - the
METHOD
andTYPE
is from thejava.lang.annotation.ElementType
package
- the
@Retention(RUNTIME)
- the
@Retention
is from thejava.lang.annotation
package - the
RUNTIME
is from thejava.lang.annotation.ElementType
package
- 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
TimedInterceptor
in theexpert.os.labs.persistence.cid.audited
package - Add the following annotations:
@Timed
@Interceptor
from thejakarta.interceptor
package@Priority(Interceptor.Priority.APPLICATION)
from thejakarta.annotation
package- the
Interceptor
is from thejakarta.interceptor
package
- the
- Define a private attribute
Logger
from thejava.util.logging
package - Create a method called
timer
that will return anObject
- it has a parameter
InvocationContext
from thejakarta.interceptor
package
- it has a parameter
- Annotate the method with
@AroundInvoke
from thejakarta.interceptor
package - 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
String
showing 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
FastSupplier
in the in theexpert.os.labs.persistence.cid.audited
package - 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
SlowSupplier
in the in theexpert.os.labs.persistence.cid.audited
package - 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
AppInterceptor
in theexpert.os.labs.persistence.cid
package -
Add a main method
-
Set up a try-with-resources block, inside the
main
method, to manage the Jakarta EESeContainer
that is responsible for dependency injection and managing resources -
Obtain the value of the
FastSupplier
through the container instance - Obtain the value of the
SlowSupplier
through 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());
}
}
}