Set Up Lifecycle-specific Actions for Injected Objects
In the above example, you have applied the @PostConstruct
and @PreDestroy
annotations to a CDI managed bean, named BallBean
. In this section, you will apply these annotations to another CDI managed bean, named RandomGenerator
that will be injected into the BallBean
with the @Inject
annotation. The idea is to separate the generation process from the main bean by writing a producer method.
A producer method is a method that acts as a source of bean instances. The method declaration itself describes the bean and the container invokes the method to obtain an instance of the bean when no instance exists in the specified context. A producer method lets the application take full control of the bean instantiation process. A producer method is declared by annotating a method of a bean class with the @Produces
annotation.
Next, you will write a producer method that returns a random value. This value will be injected into BeanBall
. The RandomGenerator
in this case, looks like below:
package com.games.balls;
import java.util.Random;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
@RequestScoped
public class RandomGenerator {
private Random generator;
@PostConstruct
private void startGenerator() {
System.out.println("*** RANDOM GENERATOR CREATED ***");
generator = new Random();
}
@PreDestroy
private void stopGenerator() {
System.out.println("*** RANDOM GENERATOR DESTROYED ***");
generator = null;
}
@Produces int getRandomNumber() {
return generator.nextInt(3);
}
}
BallBean
is modified as follows:
package com.games.balls;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
@Named
@RequestScoped
public class BallBean {
private String ballType;
@Inject int randomValue;
public void generateRandomBall() {
switch (randomValue) {
case 1:
this.ballType = "Tennis Ball";
System.out.println("*** Tennis Ball Generated ***");
break;
case 2:
this.ballType = "Volley Ball";
System.out.println("*** Volley Ball Generated ***");
break;
case 3:
this.ballType = "Football Ball";
System.out.println("*** Football Ball Generated ***");
break;
default:
this.ballType = "No Ball";
System.out.println("*** No Ball Generated ***");
}
}
public String getBallType() {
return ballType;
}
public void setBallType(String ballType) {
this.ballType = ballType;
}
}
A possible output of the GlassFish logs is listed below:
[#|2011-01-11T02:06:36.165-0800|INFO|glassfish3.0.1|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=31;_ThreadName=Thread-1;|*** RANDOM GENERATOR CREATED ***|#]
[#|2011-01-11T02:06:36.165-0800|INFO|glassfish3.0.1|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=31;_ThreadName=Thread-1;|*** No Ball Generated ***|#]
[#|2011-01-11T02:06:36.173-0800|INFO|glassfish3.0.1|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=31;_ThreadName=Thread-1;|*** RANDOM GENERATOR DESTROYED ***|#]
[#|2011-01-11T02:06:36.691-0800|INFO|glassfish3.0.1|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=31;_ThreadName=Thread-1;|*** RANDOM GENERATOR CREATED ***|#]
[#|2011-01-11T02:06:36.692-0800|INFO|glassfish3.0.1|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=31;_ThreadName=Thread-1;|*** Tennis Ball Generated ***|#]
[#|2011-01-11T02:06:36.700-0800|INFO|glassfish3.0.1|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=31;_ThreadName=Thread-1;|*** RANDOM GENERATOR DESTROYED ***|#]
You can see how the injected random generator is created and destroyed by the @PostConstruct
and @PreDestroy
annotations.
If a scope is not explicitly specified, then the bean belongs to a special scope called the dependent pseudo-scope. Beans with this scope live to serve the object into which they were injected, which means their lifecycle is bound to the lifecycle of that object.
An interesting exercise is to place the BallBean
in SessionScope
and the RandomGenerator
on the RequestScope
. Also, add to the BallBean
two methods annotated with @PostConstruct
and @PreDestroy
. In the GlassFish logs, you will see how the lifecycle of the two beans are managed depending on their scope. In addition, you can play with different kind of scopes and injections.
Original: January 28, 2011