Seam and EJB 3 integration on JBoss 5.1.0 GA

Last week a colleague (and good friend of mine) and I gave a JBoss Seam and Java ServerFaces training at company that creates tax automation products for local authorities. As a part of the training we prepared a workshop in which the participants had to build a webshop application. We decided to go with JBoss 5.1.0 GA combined with JBoss Seam 2.2 and EJB 3.0.

In this article I will share a few problems (and solutions) we encountered using Seam 2.2 and EJB 3 with JBoss 5.1.

JBoss startup bug in profiles.xml

First problem we encountered was with JBoss 5.1.0 GA. There seems to be a bug in the profiles.xml configuration that is packaged with JBoss AS that prevents the server from starting correct.

Here is the fix voor JBoss 5.1.0.GA. Open the file \jboss-5.1.0.GA\server\default\conf\bootstrap\profiles.xml
and locate the following xml fragment:

<bean name="AttachmentStore" class="org.jboss.system.server.profileservice.repository.AbstractAttachmentStore">
<constructor>
    <parameter><inject bean="BootstrapProfileFactory" property="attachmentStoreRoot" /></parameter>
</constructor>

Change it in:

<bean name="AttachmentStore" class="org.jboss.system.server.profileservice.repository.AbstractAttachmentStore">
<constructor>
    <parameter class="java.io.File"><inject bean="BootstrapProfileFactory" property="attachmentStoreRoot" /></parameter>
</constructor>
... // rest of the config without any change.

Also see: http://community.jboss.org/thread/2390

Seam EJB 3 integration

To get the Seam and EJB 3 integration working I spent almost 2 hours figuring out how to do it. Yes, it can be found in the documentation but it is not that clear as one would hope. Here are the steps to pull it of. I`m assuming that you have a separate jar project for your ejb code.

  1. Add an empty seam.properties to your ejb project.
  2. Add the seam inteceptor to the ejb-jar.xml
  3. Annotate your EJB SessionBeans with @Name
  4. Add the correct jndi-pattern for JBoss to the Seam components.xml

The ejb-jar.xml

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:ejb="http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
	version="3.0">
	<interceptors>
		<interceptor>
			<interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
		</interceptor>
	</interceptors>
	<assembly-descriptor>
		<interceptor-binding>
			<ejb-name>*</ejb-name>
			<interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
		</interceptor-binding>
	</assembly-descriptor>
</ejb-jar>

jndi-pattern

This is the part that took me way too long to figure out, you need to add the correct jndi-pattern in your seam components.xml (WEB-INF/components.xml). For JBoss this pattern is ear-name/bean-name/local (for local EJBs).

<?xml version="1.0" encoding="UTF-8"?>
<components xmlns="http://jboss.com/products/seam/components"
	xmlns:core="http://jboss.com/products/seam/core" xmlns:persistence="http://jboss.com/products/seam/persistence"
	xmlns:web="http://jboss.com/products/seam/web" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.2.xsd
                 http://jboss.com/products/seam/persistence http://jboss.com/products/seam/persistence-2.2.xsd
                 http://jboss.com/products/seam/web http://jboss.com/products/seam/web-2.2.xsd
                 http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.2.xsd">

	<core:init debug="false" jndi-pattern="ear-name/#{ejbName}/local" />
</components>

Using Seam injection for EJBs

If you annotate your stateless SessionBean, for example with @Named(“beanName”), you can start using the Seam injection in you web components. The EJB should look something like this:


@Stateless
@Name("productService")
public class ProductServiceImpl implements ProductService {
...
}

Have a you look at the web component example below, it gives an example on how to use the @In annotation to inject an EJB into your Seam component. Seam has a convention for knowing what bean you are referencing. If your bean variable instance name matches the @Named value, than the match can made by Seam. You can also explicitly specify the Bean name (@Named value) in the @In annotation. Make sure to also specify create=true on the @In or the injection will not work.


@Name("productListController")
@Scope(ScopeType.EVENT)
public class ProductListController {

	/**
	 * Injected EJB 3.0 Stateless SessionBean
	 * @see ProductServiceImpl
	 */
	@In(create=true)
	private ProductService productService;

	...
}

seam-gen

That should do the trick. If you get confused and don`t know what to do anymore. Generate an example application with seam-gen and look at the structure generated by seam-gen. Sometimes this helps ;-)

2 Responses to “Seam and EJB 3 integration on JBoss 5.1.0 GA”

  1. Jarno says:

    Vital piece of information as far as I’m concerned. I remember working until the wee hours of the morning to get this to work.

    Good to see you take the time to write this up!

  2. Krishna says:

    HI,

    This example is very good. Bugs in Jboss is known to every one. I have worked on JBoss in one of the project and faced difficulties.

    Thanks,
    Krishna

Leave a Reply