Inject Java EE Beans into Tapestry-5.x

Tapestry uses it’s own Inversion Of Control (IOC) container. Tapestry pages are not Servlets or Servlet Filter (and not another managed class). Therefore they cannot be used for injection of Java EE Beans. But there is the AppModule, which is conceptual some kind of related to Spring Java Config. It allows to configure the Tapestry application directly in Java. Like everything in Tapestry it has an Adaptive API. Hence you have to follow a naming (signature) pattern for your methods and Tapestry finds them. You don’t have to implement an interface.

A session bean may be looked up via JNDI. This can be done in a method in the AppModule, responsible for creating objects of a specific kind. The signature of such a method is as follows: Type buildType(params...);. The parameters can contain, e.g., the current Request, if some context information is necessary. The actual parameters will be injected into the method. The respective bean is injected into a Tapestry page via @Inject.

In the following I show a small example for retrieving a session bean. It can be injected into a page via @Inject private DummyController dummyController:

    /**
     * Looks up for the {@link DummyController} via JNDI. If it couldn't be
     * found this method returns {@code null}.
     *
     * @return the {@link DummyController} or {@code null} if not found.
     */
    @Scope(ScopeConstants.PERTHREAD)
    public DummyController buildSystemController(Request request, RequestGlobals globals) throws LoginException {
    	InitialContext ctx = null;
    	try {
    		final Properties env = new Properties();
    		env.setProperty("java.naming.factory.initial","org.jboss.naming.NamingContextFactory");
    		env.setProperty("java.naming.factory.url.pkgs","org.jboss.naming:org.jnp.interfaces");
    		// create a new initial context in order to have access to the JNDI of the jboss.
    		ctx = new InitialContext(env);
    		Object controller;
    		try {
    			// Whether my tapestry client is embedded in the jboss or started externally
			if (Boolean.parseBoolean(System.getProperty("myapp.external")) ) {
    				// lookup the controller.
    				controller = ctx.lookup(String.format(CONTROLLER_JNDI_NAME_REMOTE, "DummyBean"));
    			}
			else {
    				// lookup the controller.
    				controller = ctx.lookup(String.format(CONTROLLER_JNDI_NAME_LOCAL, "DummyBean"));
    			}
    			return controller;
    		}
		finally {
    			ctx.close();
    		}
    	}
	catch (NamingException e) {
    		log.warn(type + "Controller couldn't be built " + e.toString());
    	}
    	return null;
    }

This is possible for CDI beans, too. I will show that in another post.

Leave a Reply

Your email address will not be published. Required fields are marked *