03 September 2007

Getting @ an EJBContext from External Interceptors

If you need to get at the EJBContext of the target bean from an external interceptor class, then one easy way to do it with OC4J is to lookup the following resource from within the interceptor:

EJBContext context = (EJBContext)new InitialContext().lookup("java:comp/EJBContext");

In OC4J 11 even this marginal piece of code won't be necessary as the EJBContext (and any other type of resource) can be injected directly into the interceptor.

Before I was made aware of the simpler solution above, I was resorting to using some reflection code to try and work out if there was an applicable way to get the EJBContext from the target bean. It uses first a direct field check and if that yields no results, it then looks for an accessible method that has returns an EJBContext class, or a derivative thereof.

// The EJBContext classes
final List contextClasses = Arrays.asList(
new Class[] {
javax.ejb.EJBContext.class,
javax.ejb.SessionContext.class });
/**
* Try and get the principal name from the target bean class
* @param target
* @return name of the principal
* @throws Exception
*/
String getPrincipalName(Object target) throws Exception {
String ret = getPrincipalNameFromField(target);
if(ret != null) {
return ret;
} else {
ret = getPrincipalNameFromMethod(target);
}
return(ret != null ? ret : "Ghost Rider");
}

private String getPrincipalNameFromField(Object target) throws Exception {
for(Field field : target.getClass().getFields()) {
if(contextClasses.contains(field.getType())) {
EJBContext ctx = (EJBContext)field.get(target);
return ctx.getCallerPrincipal().getName();
}
}
return null;
}

private String getPrincipalNameFromMethod(Object target) throws Exception {
Method[] methods = target.getClass().getMethods();
for (Method method: methods) {
if(contextClasses.contains(method.getReturnType())) {
EJBContext ret = (EJBContext)method.invoke(target, null);
return ret.getCallerPrincipal().getName();
}
}
return null;
}


This worked pretty well in my tests, but of course it needs the target bean class to be in a cooperative form -- the EJBontext either needs to be accessible as a public field, or there needs to be a public method to get the object from the target bean.

The JNDI lookup is easier and more reliable.

No comments: