The container is Glassfish. I have implemented an @PostConstruct
life-cycle event interceptor method in a simple DAO bean class, but seems like for some reason it is not intercepting my business method at all. I do not anywhere manually instantiate the bean classes. beans.xml
discovery mode is all and since I don't annotate DefaultUserDao
bean, so it gets the default scope.
public class DefaultUserDao implements UserDao {
private String userName;
private String password;
Scanner users = null;
String[] userNamePasswordPairs = null;
public DefaultUserDao() {
try {
users = new Scanner(Paths.get("/home/NetBeansProjects/EJBInAction/web/users"));
}
catch (IOException ex) {
Logger.getLogger(DefaultUserDao.class.getName()).log(Level.SEVERE, null, ex);
}
}
/*The interceptor for this method is defined right below, that
interceptor method is not called at all. If I insert a
System.out.println(userNamePasswordPairs) after the split()
method below, it prints [userName:password] pair twice and there
is only one line in the text file from which the pair was read in the
form like this admin:admin. Notice that I also insert a System.out.println()
method in the interceptor method but if I remove the print()
method from this init() method, I don't see it prints anything
*/
@PostConstruct
public void init() {
while (users.hasNextLine()) {
String line = users.nextLine();
userNamePasswordPairs = line.split(":");
//If I uncomment this, I see it prints [admin:admin] pair
//twice, but when I comment it out, I don't see it prints anything
//System.out.println(Arrays.toString(userNamePasswordPairs));
userName = userNamePasswordPairs[0];
password = userNamePasswordPairs[1];
}
}
@AroundConstruct
private void printUser(InvocationContext ic) {
//If this interceptor was invoked, it should print at least "Interceptor invoked: "
//But it does not print this.
System.out.println("Interceptor invoked: " + Arrays.toString(userNamePasswordPairs));
try {
ic.proceed();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
A simple JSF page gathering username and password
@Named
@RequestScoped
public class LoginBean {
private String userName;
private String password;
@Inject
private UserDao userDao;
public LoginBean() {
}
public LoginBean(String userName, String password) {
this.userName = userName;
this.password = password;
}
public String validateUser() {
if (userDao.getUserName().equals(userName) && userDao.getPassword().equals(password)) {
}
else {
userName = "Error";
password = "Error";
}
return "confirmation.xhtml";
}
//getter and setter for userName and password
}
First, note that @PostContruct
is a lifecycle callback - and not an interceptor - while @AroundConstruct
is an interceptor method. They have different meanings and are declared differently.
Also note that the invocation order is typically the following:
proceed()
method in the interceptor.@Inject
fields/setters are set)@PostConstruct
lifecycle callback is called.Regarding the @PostConstruct
lifecycle callback, you declare it correctly. And It seems to be called since it prints some text.
Regarding the interceptor, the following is missing:
META-INF/beans.xml
file under the <interceptors>
element OR it must be annotated with the javax.annotations.Priority
annotation specifying a priority value. The later option makes your interceptor application-wide, basically: it will apply to the whole app instead of just the jar containing the META-INF/beans.xml
. To start, I recommend you declare it in the META-INF/beans.xml
.@Interceptor
(javax.interceptor.Interceptor
)To summarize, you have to create an interceptor binding for your interceptor:
@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface Greet {
}
Then you have to create a class for your interceptor, using the interceptor binding:
@Greet
@Interceptor
public class GreetInterceptor {
@AroundConstruct
public void aroundConstruct(InvocationContext ic) throws Exception {
System.out.println("Hello!!");
ic.proceed();
}
}
Then declare it in your META-INF/beans.xml
:
<interceptors>
<class>com.sandbox.GreetInterceptor</class>
</interceptors>
Finally, annotate the bean you want to intercept calls with the interceptor binding:
@Greet
public class DefaultUserDao implements UserDao {
...
}