Posts

Showing posts from June, 2009

Tomcat - load & bind an external naming context

In my previous post Injecting JBoss EJB3 beans into Tomcat6, I used Tomcat's ability to bind EJB's to the local JNDI context by specifying JBoss' NamingContextFactory and the URL to the EJB. However in the process of using it, I discovered a problem with Stateful Session Beans.

I was getting NoSuchEJBException - either after a redeploy to JBoss, or calling the @Remove annotated method on the session bean. A lot of debugging later, I discovered that the cause was that Tomcat was initially storing a ejb ref (org.apache.EjbRef) in the context and when first accessed it looks up the EJB using the factory and then replaces the reference in the context with the instance of the EJB. Every subsequent lookup in the context returns the same instance.

This however breaks the JEE5 contract:
FROM JSR 220: NOTE: When a stateful session bean is looked up or otherwise obtained through the explicit JNDI lookup mechanisms, the container must provide a new stateful session bean instance, as r…

Injecting JBoss EJB3 beans into Tomcat6

Injecting EJB's into a managed bean (a bean spawned by appserver, of a JSF managed bean) inside an application server is simple:
public class AppManagedBean { @EJB(mappedName="ejb/myBean") private MyBeanRemote session;The container looks up the mapped bean and injects it. Easy.

However in tomcat it gets a little messy. Tomcat doesn't document how to inject them. It assumes something annotated with @EJB is in the context somewhere and tries to look it up.
It has documented how to lookup ejb's by defining entries in your context.xml or server.xml. But there isn't anything documented for defining EJB's. Looking at the soure it has support for <Ejb/> references but no real clue on how to configure it. So after stepping through the code I came up with the following soloution:

My environment is JBoss 5 running remotely (on localhost). A seperate instance of Tomcat 6. In it I have defined a session bean:
@Stateful(mappedName="userSession") pu…

Change user name in eclipse

The code comment templates are handy for inserting the author of a class, which is handy in rather large projects. For example, here is my template for types(classes):/**
* @author ${user}
*
* ${tags}
*/
However under windows (and probably *nix as well) it just inserts the current user name. But I want it always to display my real name - which is more meaningful when employees come and go.

You can change it by passing this argument on the comment line:
You need to put it at the end of your command line.
eclipse.exe -vmargs -Duser.name="You real name"

A few good Guice Tutorials

I came across these rather good Guice tutorials in trying to find a way to integrate Google Guice in an application server (EJB3).

Part 1: a quick intro.
Part 2: method interceptors.

This was the tricky one, how to inject EJB's which are created by the container without having to have every class extend a base class with a @PostConstruct annotated method to do the injecting. The solution was to use the new interceptors introduced into JEE 5.
Part 3 – Integrating Guice with EJB
If you want a little background, see EJB Interceptors.

CommandButton not calling action when using immediate and rendered

I came across a problem with using a custom command component, that when using immediate it wasn't calling the action I had bound to it. I started resolving the issue and discovered my decode code wasn't being called. I had create a custom button, cannibalising and extending the original CommandButton component. Due to my lack of understanding of setting up renderkits, I gave up and hacked in a renderer:
public class ImageButton extends HtmlCommandButton { private ImageButtonRenderer render = new ImageButtonRenderer(); @Override public void decode(FacesContext context) { render.decode(context, this); } @Override public void encodeBegin(FacesContext context) throws IOException { render.encodeBegin(context, this); }This resulted in decode not always working. I came across this nice summary of how to write a custom component and altered my code accordingly. Decode worked but the action was still not called. Thought the cause was just…

ClassCastException with PortableRemoteObject.narrow() EJB2/EJB3

After switching to JBoss 5 and recreating my EAR project inside eclipse, I started getting ClassCastException:
java.lang.ClassCastException
at com.sun.corba.se.impl.javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:229)
at javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:137)Object obj = initialContext.lookup(ejbReferenceComponent);
MyEJBRemoteHome home = javax.rmi.PortableRemoteObject.narrow(obj, MyEJBRemoteHome.class);
After looking around, the cause of it is how the app server determines whether to give you a EJBHome instance which you have to use .narrow() then .create() to get a reference to the bean for EJB2 vs returning a proxy to the bean itself for EJB3. JBoss has some information on referencing EJB3 from EJB2 environments and vice-versa.

The summary generally is if the application.xml has the EJB2 header then it gives you an EJBHome interface.
If the ear's ejb-jar has the EJB3 header then it gives you a proxy to the bean itself (no need for nar…