现在的位置: 首页 > 综合 > 正文

Integrating Seam with Maven, Netbeans and GlassFish

2012年04月12日 ⁄ 综合 ⁄ 共 14714字 ⁄ 字号 评论关闭

The application that resulted from my previous article on Maven, Netbeans and GlassFish
uses Hibernate for JPA and Facelets for JSF. This is an ideal situation
to make the move to Seam. In the past few weeks I have spent some time
on using Seam in GlassFish applications but I haven’t been very
successful. However, the jpa example that is shipped with the Seam
2.0.0 GA distribution shows that working with Seam on Glassfish can be
very simple. I just built the GlassFish war suing ant and deployed that
war to GlassFish. The application just ran without any problems at all!
Today I finally managed to build a Seam application for GlassFish.
Moving that application to Maven then was very easy. This article will
tell you how to do it.

I will assume that you have followed the
instructions for
creating a Maven enabled Hibernate/Facelets application in Netbeans. If
you haven’t then that’s no problem. This article should provide you
with enough hints to enable Seam on any Enterprise Application created
with Netbeans.

....

Moving the EJB module to Seam

The
number of jars that are needed to enable Seam on the EJB module is very
very small: just 1. It is the jboss-seam.jar file. The reason only this
jar is needed, is that the jars, that the jboss-seam.jar depends on,
already have been installed into the GlassFish lib directory when we
moved from Toplink Essentials to Hibernate. These jars are dom4j.jar,
el-api.jar, hibernate-validator.jar and javassist.jar. Well, the
el-api.jar file classes are actually contained in the GlassFish
javaee.jar file. Besides these jars, the jboss-seam.jar file also
depends on the jboss-el.jar file. We won’t need this jar for the
application that we’ll build in this article, but you may want to
include that jar anyway in case you’d want to use EL expressions in
your entity classes.

Please note
that I have updated the list of jars files needed for Hibernate in my
previous article. You should now also copy the hibernate-validator.jar
file from the Hibernate EntityManager distribution to the GlassFish lib
directory. If you haven’t done so, please do it now!

Before
we can make Maven download the seam jars, we need to add another
repository to our pom.xml file. Since this repository will also be used
by the WAR module, I have included it in the Parent Pom Module pom.xml
file. The lines to add are these

        <repository>
<id>jboss.org</id>
<name>jboss.org</name>
<url>http://repository.jboss.com/maven2</url>
</repository>

Next, these lines in the EJB module pom.xml file will make Maven download the needed jars

        <dependency>
<groupId>org.jboss.seam</groupId>
<artifactId>jboss-seam</artifactId>
<version>2.0.0.GA</version>
<exclusions>
<exclusion>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
</exclusion>
<exclusion>
<artifactId>el-api</artifactId>
<groupId>javax.el</groupId>
</exclusion>
<exclusion>
<artifactId>javassist</artifactId>
<groupId>jboss</groupId>
</exclusion>
</exclusions>
</dependency>

At
this stage you may want to Clean And Build the project so the jars get
downloaded and Netbeans is capable of locating the classes in the jars.
Once done we can annotate our DataBean session bean with the @Name
annotation. Besides that, we can switch over to Seam managed
persistency instead of container managed persistency. This means that
we need to replace the @PersistenceContext annotation with the @In
annotation.

Besides that we’ll need to adjust the DataBean
class to conform the Java Bean design guidelines. These guidelines
state that Beans contain (private) member variables with getters and
setters. To be able to keep on using the "countEmployees" call in our
index.xhtml file, we’ll need to introduce a (private) int
countEmployees and rename the countEmployees() method to
getCountEmployees(). Please note that renaming the method in the
DataBean class means that you’ll have to rename the countEmployees
method definition in the DataLocal interface as well!

The final DataBean class looks like this

package nl.amis.maven.enterprise.ejb.session;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;

@Stateless
@Name("dataBean")
public class DataBean implements DataLocal {

@In EntityManager em;

private int countEmployees;

public int getCountEmployees() {
return em.createNamedQuery("Employees.getAll").getResultList().size();
}

}

That
nearly completes the modifications that the EJB module needs. We only
need to create two more files, one of which is empty, and modify our
persistence.xml file. Lets start with the empty file.

Expand the
Other Sources -> resources -> META-INF node. Right click the
META-INF node and select New -> Other … and choose Properties File
from the Other category. Name this file "seam" (without the queotes and
without the .properties extension) and click Finish. This file will
trigger Seam to initiate and load all classes and resources in the EJB
module.

While we’re in this node, let’s create the second file.
This file will be an XML file (New -> Other … and choose XML
document from the XML Category) and name this file "ejb-jar". This file
will contain some Seam specific interceptor definitions. The contents
of this file should be

<?xml version="1.0" encoding="UTF-8"?>

<ejb-jar xmlns = "http://java.sun.com/xml/ns/javaee"
version = "3.0"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">

<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>

Finally,
we need to modify the persistence.xml file to define Seam managed
persistency. Double click the persistence.xml file in the META-INF node
and make the contents look like this

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="MavenEnterpriseApplicationEjbPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<non-jta-data-source>jdbc/hr</non-jta-data-source>
<properties/>
</persistence-unit>
</persistence>

Please
note two important things. first of all, we switched from transaction
type JTA to RESOURCE_LOCAL. This means that Seam will be in charge of
the transactions etc. This means that we will need to modify our data
source definition from jta-data-source to non-jta-data-source. Besides
that I slightly modified the persistence-unit name. It was
MavenEnterpriseApplication-ejbPU but unfortunately Seam won’t accept
the dash ("-") in the name.

That’s it for the EJB module.

Moving the WAR module to Seam

Moving
the WAR project to Seam also isn’t very complicated. First we need to
include the needed dependencies in our pom.xml file. The WAR module
needs two of them: jboss-seam-ui.jar and jboss-el.jar. Again, these two
jars depend on several jars that already have been installed in the
GlassFish lib dir, so we may exclude them. Add these lines to your
pom.xml file

        <dependency>
<groupId>org.jboss.seam</groupId>
<artifactId>jboss-seam-ui</artifactId>
<version>2.0.0.GA</version>
<exclusions>
<exclusion>
<artifactId>commons-beanutils</artifactId>
<groupId>commons-beanutils</groupId>
</exclusion>
<exclusion>
<artifactId>dom4j</artifactId>
<groupId>dom4j</groupId>
</exclusion>
<exclusion>
<artifactId>el-api</artifactId>
<groupId>javax.el</groupId>
</exclusion>
<exclusion>
<artifactId>javassist</artifactId>
<groupId>jboss</groupId>
</exclusion>
<exclusion>
<artifactId>jboss-seam</artifactId>
<groupId>org.jboss.seam</groupId>
</exclusion>
<exclusion>
<artifactId>jsf-api</artifactId>
<groupId>javax.faces</groupId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.jboss.seam</groupId>
<artifactId>jboss-el</artifactId>
<version>2.0.0.GA</version>
<exclusions>
<exclusion>
<artifactId>el-api</artifactId>
<groupId>javax.el</groupId>
</exclusion>
</exclusions>
</dependency>

Clean
and Build the project so the jars get downloaded. Doing so will make
Maven resolve all dependencies. This will make Maven see that the EJB
module depends on jboss-seam.jar and this library will show up in the
list. however, this jar is not needed here. If you like you can exclude
it by adding these lines to the EJB modulle dependency in the WAR
module pom.xml file

            <exclusions>
<exclusion>
<groupId>org.jboss.seam</groupId>
<artifactId>jboss-seam</artifactId>
</exclusion>
</exclusions>

Since
Seam will be in charge on injecting (and outjecting) bean references,
we won’t need the Managed Bean reference in the faces-config.xml file
anymore. So, expand the Web Pages -> WEB-INF node and remove the
managed bean code from the faces-config.xml file. For Seam to be able
to resolve the bean references correctly, the web.xml file also needs
to be modified. Open the file and add these lines at the top of the file

    <listener>
<listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
</listener>

Finally,
Seam needs another configuration file called components.xml. This file
will, among onther things, enable Seam to setup the persistence unit
and to find the session bean in our EJB module. Simply create another
XML Document in the WEB-INF directory and name it "components". This is
the components.xml file I stole from the Seam jpa example

<?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:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.0.xsd
http://jboss.com/products/seam/persistence http://jboss.com/products/seam/persistence-2.0.xsd
http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.0.xsd">

<persistence:entity-manager-factory name="MavenFaceletsSeamEjbPU"/>

<persistence:managed-persistence-context name="em"
auto-create="true"
entity-manager-factory="#{MavenFaceletsSeamEjbPU}"/>

<core:init jndi-pattern="java:comp/env/#{ejbName}" />

</components>

Please
note that the persistence name should be the same as in the
persistence.xml file in your EJB module. Besides that, Seam won’t be
able to resolve the JNDI names of session beans on GlassFish. I’m not
sure why this is so, but Seam NEEDS the jndi-pattern line. The pattern
can be anything you like. For me the "java:comp/env/#{ejbName}" pattern
will make the DataBean bean be registered under the JNDI name
"java:comp/env/DataBean" as this GlassFish log shows

Component: org.jboss.seam.core.init, scope: APPLICATION, type: JAVA_BEAN, class: org.jboss.seam.core.Init
Installing components…
Component: MavenEnterpriseApplicationEjbPU, scope: APPLICATION, type: JAVA_BEAN, class: org.jboss.seam.persistence.EntityManagerFactory
Component: dataBean, scope: STATELESS, type: STATELESS_SESSION_BEAN, class: nl.amis.maven.enterprise.ejb.session.DataBean, JNDI: java:comp/env/DataBean
Component: em, scope: CONVERSATION, type: JAVA_BEAN, class: org.jboss.seam.persistence.ManagedPersistenceContext

There
is one more catch to resolve. Since our session bean is packaged in a
jar file, the reference to the bean needs to be made explicit in
web.xml. This can be done with a "ejb-local-ref" element like this

    <ejb-local-ref>
<ejb-ref-name>DataBean</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>nl.amis.maven.enterprise.ejb.session.DataLocal</local>
</ejb-local-ref>

That’s
it! The ejb-ref-name element makes sure that the "#{ejbName}" part in
the jndi-pattern line in the components.xml file is referring to the
right value. Please note that this needs to be done for ALL beans that
are packaged in the EJB module jar and that need to be references from
your xhtml pages. That was easy right?

O wait, one more thing and
then we’re finished. Promise. We need to modify the index.xhtml file to
make use of the DataBean bean instead of the NumberBackingBean. So,
open the index.xhtml file and modify the EL expression to

#{dataBean.countEmployees}

Once
more rebuild the application and now fire the exec:exec goal on the EAR
module. Once your application has been deployed, browse to e.g.
http://localhost:8280/MavenEnterpriseApplication-war/index.jsf and you
should once more see

Next steps

Since
Seam now is in charge of the transaction and Entity Manager management,
the Hibernate jars are no longer needed in the GlassFish lib directory.
You may remove them and then restart GlassFish. This will mean that you
need to deploy those jars with your application. This, of course, can
be done by modifying the pom.xml files and add the correct
dependencies. To do this, I used the list below in the EJB pom.xml and
made no modifications to the WAR pom.xml file. Please note that the
list below only replaces the Hibernate dependencies. No modifications
are needed for the Seam dependencies. Adding the dependencies to the
EJB pom.xml will make Maven include the jars both in the EJB jar and in
the WAR thus making sure that both modules have the jars they need. It
would help to clean up the redundant jars but I’ll leave that up to you
to do Smiley

    <dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.5.ga</version>
<exclusions>
<exclusion>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.3.0.ga</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>3.3.0.ga</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.3.1.ga</version>
<exclusions>
<exclusion>
<artifactId>jboss-common-core</artifactId>
<groupId>jboss</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>3.0.0.ga</version>
</dependency>
<dependency>
<groupId>antlr</groupId>
<artifactId>antlr</artifactId>
<version>2.7.7</version>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>1.5.3</version>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm-attrs</artifactId>
<version>1.5.3</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.1_3</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1</version>
<exclusions>
<exclusion>
<artifactId>avalon-framework</artifactId>
<groupId>avalon-framework</groupId>
</exclusion>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
<exclusion>
<artifactId>logkit</artifactId>
<groupId>logkit</groupId>
</exclusion>
<exclusion>
<artifactId>servlet-api</artifactId>
<groupId>javax.servlet</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>concurrent</groupId>
<artifactId>concurrent</artifactId>
<version>1.3.4</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
<exclusions>
<exclusion>
<artifactId>xml-apis</artifactId>
<groupId>xml-apis</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>jboss</groupId>
<artifactId>javassist</artifactId>
<version>3.3.ga</version>
</dependency>
<dependency>
<groupId>jboss</groupId>
<artifactId>jboss-archive-browsing</artifactId>
<version>5.0.0alpha-200607201-119</version>
</dependency>
<dependency>
<groupId>javax.ejb</groupId>
<artifactId>ejb-api</artifactId>
<version>3.0</version>
<scope>provided</scope>
</dependency>

抱歉!评论已关闭.