JEE6 – How to package an EAR – Part II.

As I explained in my previous blog entry about JEE6 ear packaging, there is a flexible and powerful way to deploy EARs containing JEE component libraries.

Using maven makes it much easy to build such ear deployment units. The interessting part of the pom.xml of the ear module looks something like this:

 

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-ear-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <version>6</version>
                    <modules>
                        <webModule>
                            <groupId>myweb</groupId>
                            <artifactId>imixs-web</artifactId>
                            <contextRoot>/test</contextRoot>
                        </webModule>
                        <ejbModule>
                            <groupId>myejb</groupId>
                            <artifactId>imixs-ejb</artifactId>
                        </ejbModule>
                        <JarModule>
                            <groupId>org.imixs.workflow</groupId>
                            <artifactId>imixs-workflow-engine</artifactId>
                            <bundleDir>/</bundleDir>
                        </JarModule>                        
                    </modules>
                </configuration>
            </plugin>
        </plugins>
 ....

In this example the artefact ‘imixs-workflow-engine’ is a component library containingg EJBs. You can refere to those libraries from your ejb module (in this example ‘myejb’) by using the ‘manifestEntries’ tag in your maven ejb module configuration. This is what I explained here.

But what if you need some more additional external libraries containing non-jee-components (simple pojo’s like for example apache commons-xx.jars) ?

You can add those dependencies to your ear pom.xml – so these jars will also become part of the ear root directory. But now you need to add them again to the manifest file of your ejb module if you need access to these libraries. And this will result in a strange situation because indirect dependencies will make it impossible for you to manage your manifest file manually.

I run in this situation when a need the apache fop-1.0 library in one of my ejb components.

But the solution is again quite simple when using maven and the ear-plugin. The plugin provides a configuration tag named ‘defaultLibBundleDir’. And you simply need to the the value to ‘lib’ to get all your libraries moved in the default lib directory of an ear:

<plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-ear-plugin</artifactId>
       <version>2.6</version>
       <configuration>
            <version>6</version>
            <defaultLibBundleDir>lib</defaultLibBundleDir>
            <modules> 
         .....
  ....
</plugin>

But you need to be careful because also your jee-component libraries will be moved into that location if you did not overwrite the default behaviour now.  You can do this by declaring each of your jee component libraries as a ‘JarModule’ where you specifiy the ‘bundleDir’ with ‘/’:

....
<module>
 ....
  <JarModule>
       <groupId>org.imixs.workflow</groupId>
       <artifactId>imixs-workflow-core</artifactId>
       <bundleDir>/</bundleDir>
  </JarModule>
</module>
...

This will result in a ear structure where your own jee-components will become part of the root of your ear, and all other library dependencies will be moved to the /lib directory of your ear. So any libary can be seen from your ejb, web and component modules. And you jee-component.jars will still be parsed for JEE annotations during deployment.

I hope this helps you to build you own custom enterprise applications using all the strength of JEE.

 

Glassfish – 3.1.X – CDIExtension not found

Today I run into a problem when trying to deploy a EAR with more than one web modules using CDI. Deploying such a EAR on Glassfish 3.1.1 or 3.1.2 will fail with the following exception:

Root exception is javax.naming.NameNotFoundException: CDIExtension not found

As you can read in this posting this is a known bug.

http://www.java.net/forum/topic/glassfish/glassfish/gf-311-jdk1716-linux-64bit-application-running-windows-7-does-not-deploy-linux

 

http://java.net/jira/browse/JERSEY-601

 

You can solve the problem when setting the system-property “com.sun.jersey.server.impl.cdi.lookupExtensionInBeanManager=true”.

This can be done from the GlassFish server console.

  • Select the node ->Configuration->server-config->JVM Settings
  • change to the tab ‘JVM Options’
  • add a new entry
    -Dcom.sun.jersey.server.impl.cdi.lookupExtensionInBeanManager=true
  • restart your server

This will solve the deployment problem.

 

JSF 2.0 and the xmlns:c namespace

If you are working with JSF 2.0 there is a important change concerning the JSF core tags (<c:….>). These tags will not work if you are using the following namespace declaration:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"  
    xmlns:c="http://java.sun.com/jstl/core" 
    xmlns:h="http://java.sun.com/jsf/html">

This works in JSF 1.2 but well, but did no longer work in JSF 2.0. The reason is that the namespace uri for the jstl/core has changed. Use the following namespace definition if you are working with jsf 2.0

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"  
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:h="http://java.sun.com/jsf/html">

 

JSF 2.0 – The action event model

If you are working with JSF 2.0 there are different ways to interact with backend methods and passing params to action methods. A useful link for this topic can also seen here.

So for example if you have a JSF page with the following command link you use different ways to bound your backing bean:

<h:commandLink action="#{workflowController.editAction(workitem)}"
               actionListener="#{workflowController.doEdit}">
         <h:outputText value="click me" />
         <f:setPropertyActionListener
               target="#{workflowController.workitem}" value="#{workitem}" />
</h:commandLink>

The important thing here is the order which the jsf framework will trigger the differnt methods of the backingBean ‘worklfowController’

  1. The actionListener method will be called
  2. The setPropertyActionListener will trigger the setter method of the property ‘workitem’
  3. The action method with a custom param will be called

So in this case you backingBean can look something like this – note that there are two different ways to pass a param:

 

   // first the actionListener method will be called   
   public void doEdit(ActionEvent event) throws Exception {
        // do something...
       .....
    }

   // next the setter for the property will be called
   public void setWorkitem(Data aworkitem) {
        // do something    
   }

   // last the action method will be called
   public String editAction(String action) {
        // do something
        return action;      
    }

 

JUnit and Glassfish 3.1.1 – remote ejb tests

Trying to run a JUnit Test with remote EJB lookups from a GlassFish server 3.1.1 it is a little bit tricky. It seems to me that it is not possible to get the maven dependencies working. The gf_client.jar can not be included using a dependency, although the artefact can be located using the glassfish repository from java.net :

    .....
      <!-- Glassfish -->
          <repository>
                 <id>glassfish-repository</id>
                 <name>Java.net 
                 Repository for Glassfish</name>
                <url>http://download.java.net/maven/glassfish</url>
          </repository>
.....

..and adding a dependecy:

    ...
    <dependency>
            <groupId>org.glassfish.appclient</groupId>
            <artifactId>gf-client</artifactId>
            <version>3.1.1</version>
            <scope>test</scope>
        </dependency>
....

But after all this wont work for me. So the best way is to add the gf_client.jar directly into your classpath.

The gf_client.jar is located in your Glassfish Installation at

$GLASSFISH_HOME/glassfish/lib/gf-client.jar

 

Now you can write a JUnit test with a remot ejb lookup. See the following example for a remote lookup to Imixs Entity Service

 public class TestEntityService {
    EntityServiceRemote entityService = null;

    @Before
    public void setup() {
        try {
            // set jndi name
            String ejbName = "java:global/imixs-workflow-web-sample-0.0.5-SNAPSHOT/EntityService!org.imixs.workflow.jee.ejb.EntityServiceRemote";
            InitialContext ic = new InitialContext();
            entityService = (EntityServiceRemote) ic.lookup(ejbName);
        } catch (Exception e) {
            e.printStackTrace();
            entityService = null;
        }
    }

    @Test
    @Category(org.imixs.workflow.jee.ejb.EntityServiceRemote.class)
    public void testService() {
        Assert.assertNotNull(entityService);
        //....

    }

Note: To run this JUnit test you have to first deploy your test application. After that you junit test can be run.

TESTING SECURED EJBS

If your remote ejb is annotated with the security annotation @RolesAllowed you need to authenticate your remote lookup.

In GlassFish this can be done using the programmatic Login. To setup a programmatic login in your JUnit test first create a File named ‘auth.conf’. The content of that file should look like this:

default { 
com.sun.enterprise.security.auth.login.ClientPasswordLoginModule required debug=false; 
};

Now you can add the programmatic login into your test setup

     @Before
    public void setup() {

        try {
            // set jndi name
            String ejbName = "java:global/imixs-workflow-web-sample-0.0.5-SNAPSHOT/EntityService!org.imixs.workflow.jee.ejb.EntityServiceRemote";
            // setup programmatic login for GlassFish 3
            System.setProperty("java.security.auth.login.config", "/home/rsoika/eclipse_37/imixs-workflow/imixs-workflow-engine/src/test/resources/auth.conf"); 
            ProgrammaticLogin programmaticLogin = new ProgrammaticLogin(); 
            // set password
            programmaticLogin.login("Anna", "anna"); 
            InitialContext ic = new InitialContext();
            entityService = (EntityServiceRemote) ic.lookup(ejbName);
        } catch (Exception e) {
            e.printStackTrace();
            entityService = null;
        }
    }

Note: the username/password is defined in this case in a file realm which is the default security realm of my GlassFish

Here are some helpful links:

http://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#StandaloneRemoteEJB

http://www.coderanch.com/t/476090/EJB-JEE/java/EJB-Realms-Remote-Clients

 

GlassFish – Heapsize settings

After playing around with some VM settings in my GlassFish 3.1.1 environment (development and productive) I came to a setup which brings up my glassfish server much faster. Here are my settings

Development (3GB RAM)

-client
-XX:+AggressiveHeap
-Xmx1024m
-Xms1024m
-Xss128k
-XX:+DisableExplicitGC

 

Productiv (4GB Ram)

-server
-XX:+AggressiveHeap
-Xmx2048m
-Xms2048m
-Xss128k
-XX:+DisableExplicitGC

Here is also a useful link for further performance settings:

http://jfarcand.wordpress.com/2009/11/27/putting-glassfish-v3-in-production-essential-surviving-guide/

 

 

GlassFish – EJB timer service not available

Today I had a situation where after a hardware crash my GlassFish Server did not work correctly. Specially the timer service did no longer work. The server log shows a lot of errors about

...EJB Timer Service not available

In the easiest case the reason why the timer service did not start are old db.lck files.

You can check this by stopping the server and then look for any lock files in the domain folder

../lib/databases/ejbtimer/

After removing the files

dbex.lck  
db.lck

you can restart the server and every thing should work again.

See also the following thread if this did not work for you:

http://forums.java.net/node/666385

Rest Service and the HTTPServletReqeust Object

Today I got a strange problem with my REST service which needs a HttpServletRequest object to perform the RemoteUser name.

First I injected the HttpServletRequest as a field into my RestService-Class

....
@Path("/")
@Produces({ "text/html", "application/xml", "application/json" })
@Stateless
public class SystemRestService {
 ...   
	@javax.ws.rs.core.Context
	private static HttpServletRequest servletRequest;
.....

This works fine on my local glassfish server 3.1.1. But after I deployed this into my productive environment (glassfish 3.1) the field ‘servletRequest’ was always null.

The problem here is that injecting the HttpServletRequest into an instance field can become very soon stale. The solution is to annotating a method parameter to assure that the request object is obtained in connection to processing a request.

... 	
@GET
	@Path("/profile.json")
	@Produces("application/json")
	public String getUserByID(@QueryParam("uid") String user,
			@QueryParam("items") String items,@Context HttpServletRequest servletRequest) {
.....

See also this discussion on the coderanch:

http://www.coderanch.com/t/510941/Web-Services/java/Print-Client-IP#2649412

Character encoding de_DE on Linux Debian

On my debian server today I run into a problem with the encoding of XSL templates running on a GlassFish server. The problem was that German characters where not displayed correctly.

After a long time of searching, I figured out that the reason for that problem was not my MySQL database, nor my GlassFish installation. It was simply the missing German language support on my linux debian.

You can test the installed locales with the following command:

locale -a

In my case only ‘en_US.utf8’ was listed.

In debian you can simply add the german language support by changing the file /etc/locale.gen. Simply uncomment the lines:

de_DE ISO-8859-1
de_DE.UTF-8 UTF-8
de_DE@euro ISO-8859-15

and run the command:

locale-gen

After restarting my GlassFish server the xsl transformation works fine with german characters.

The command “locale -a” now displays the following locale:

C
de_DE
de_DE@euro
de_DE.iso88591
de_DE.iso885915@euro
de_DE.utf8
deutsch
en_US.utf8
german
POSIX

Java EE6 – How to package an EAR

I spent the last weeks a lot of time to find out what’s the best way of packaging an EAR deployable on a JEE6 Application Server like Glassfish V3. I stumble on some problems when I try to deploy my EAR on Glassfish V3 which was running before on JEE5 Glassfish V2.1 server. Now I find out the missing parts and I want to describe my experiences here.

I am not talking about the typical EAR packaging situation you can see in the most of examples and tutorials where you have an EJB Module containing you business logic and a WEB Module containing your web frontend. As in JEE5 also in JEE6 it is pretty easy to deploy such an application. And there is in most cases no need to think about deployment descriptors as it was necessary before in J2EE (Java 1.3, 1.4).

What I tried to find out was the right packaging of an EAR including different libraries containing JEE components like EJBs, JPA Entities and Servlets on top of my EJB and WEB Module. I call such libraries “Component-Libraries” to indicate that these libraries containing JEE Components which can be used out of the box.

So first lets take a look on a simple situation where you want to package a simple JAR file together with a EJB and Web module. For example you have a JAR providing some POJOs used by both modules (EJB and web module). In this situation you can drop such a library simply into the /lib folder of you EAR. So your EAR should have the following structure:

[my-ear]
 - [lib]
     |- (pojo.jar)
 - [META-INF] 
     |- application.xml
     |- sun-application.xml
 - (my-ejb.jar)
 - (my-web.war)

As the pojo.jar is packaged into the /lib folder (which is the default location for shared libraries) both modules (the web and the ejb) can access the pojo.jar library. This is a typical situation and it is very easy to use.

But what if you have a component-library containing additional EJBs? If you package this library also into the /lib location like this:

[my-ear]
 - [lib]
     |- (pojo.jar)
     |- (ejb-components.jar)
 - [META-INF] 
     |- application.xml
     |- sun-application.xml
 - (my-ejb.jar)
 - (my-web.war)

the deployment will fail in most cases. The problem now is, that the EJBs  defined in the ejb-components.jar are in the top-level “lib” directory of the ear. That means the classes are visible to all modules in the ear. Each module (the my-ejb.jar and also the my-web.war) is processed for annotations, so the beans defined in the ejb-components.jar are created more than once. This is the reason that it is not recommended to put classes with component-defining annotations in a library .jar!

Ok – so lets put the ejb-components.jar out of the /lib folder location:

[my-ear]
 - [lib]
     |- (pojo.jar)
 - [META-INF] 
     |- application.xml
     |- sun-application.xml
 - (my-ejb.jar)
 - (my-web.war)
 - (ejb-components.jar)

But now the EJBs of the ejb-components.jar will not be deployed because this jar is not a declared as an ejb module. Ok – you can add the jar to the application.xml file and declare this jar to an additional ejb module like this:

<application xmlns="http://java.sun.com/xml/ns/javaee" 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/application_5.xsd" version="5">
  <module>
    <web>
      <web-uri>my-web.war</web-uri>
      <context-root>/my-web</context-root>
    </web>
  </module>
  <module><ejb>my-ejb.jar</ejb></module>
  <module><ejb>ejb-components.jar</ejb></module>
</application>

This will work until you have to overwrite the ejb-jar.xml file. But this situation often occurs if you need to reconfigure the EJBs of the ejb-components.jar. And as you have no sources of this jar you can not easily rebuild it with additional descriptors. So now you have a real problem!

But there is a trick which enables you to take over control of all the EJBs defined in the ejb-componets.jar directly in your my-ejb.jar where you have the sources to build this module.
Simply add a Class-Path definition to the META-INF/MANIFEST.MF file of your ejb module:

Manifest-Version: 1.0
Class-Path: ejb-components.jar

Now the ejb-components.jar become a part of your my-ejb.jar and you can overwrite each setting in you ejb-jar.xml file. If you are using maven as your build tool you can add this additional Manifest entry simply by using the maven-ejb-plugin.

            .......
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-ejb-plugin</artifactId>
                <configuration>
                    <ejbVersion>3.0</ejbVersion>
                    <archive>
                        <manifestEntries>
                            <Class-Path>ejb-components.jar</Class-Path>
                        </manifestEntries>
                    </archive>
                </configuration>                
            </plugin> 
            .......

If you are not using maven simply add the MANFIFEST.MF file into your my-ejb module.

OK why did I talking about all this stuff? In the situation I describe here I assume that your are not in the role of the component-developer of the EJBs implemented in the ejb-components.jar. Your are in the Role of the component-deployer. In this role you do not change the implementation but you may want to overwrite some settings of the ejbs provided by the component-developer. For example you want to define a ‘run-as-principal’ role to a ejb or a method. Or you would like to rename a ejb or inject a local jndi-mail or jndi-directory resource by name. In this cases you can do this now by the ejb-jar.xml which is located in your ejb modle (my-ejb.jar) and which is under your control.

Remember – JEE is in first place a component architecture. This means you develop an ejb component once and you can reuse and run this component everywhere in your environment. I think this part of JEE is sometimes missed in lots of JEE projects. So this concept follows the goal to simplify your deployment and your project structure but also reuse complex components in an easy way.

SERVLETS AND JPA ENTITIES

Until now I explained how to deploy ejb component jars. Next I want to take a look on another kind of JEE components – Servlets and JPA Entities.

If you have a jee-component.jar containing Servlets you can follow the instructions above. A servlet provided by the ejb-components.jar will be visible to a web module as your my-ejb.jar is part of your EAR. But your servlet will not able to use injected EJB or JNDI Ressources. So an annotation with an EJB injection in your servlet code will not work:

public class WorkflowRestService extends javax.servlet.http.HttpServlet
		implements javax.servlet.Servlet {
.... 
    @EJB
    org.imixs.workflow.jee.ejb.EntityService entityService;
.....

The reason why the entityService EJB in this case will not be injected is that the servlet class located in the ejb-componets.jar is visible to the web module but the servlet will not be scanned for injections because it is now part of our EJB module. So it is not recommended to deploy a component-library containing a servlet in the way described before.

Component-libraries containing Servlets and also JPA Entities can be still placed into the /lib location of your EAR.

[my-ear]
 - [lib]
     |- (pojo.jar)
     |- (servlet-components.jar)
     |- (jpa-components.jar)
 - [META-INF] 
     |- application.xml
     |- sun-application.xml
 - (my-ejb.jar)
 - (my-web.war)
 - (ejb-components.jar)

In this case your servlet from the servlet-components.jar is visible now to the web module (my-web.war) and Injection will work as expected. So do not! mix up EJB, JPA and WEB components into one component-library. This is also important as you increase the deployment flexibility of your project for future.

I the case of the jpa-components.jar there is another detail to be pointed out.

I assume that the jpa-comonents.jar includes Entitie EJBs like this:

package org.imixs.workflow.jee.jpa;
.....
 @javax.persistence.Entity
public class Entity implements java.io.Serializable {
......

The Entities are typical injected by EJB components using an JPA EntityManager

    @PersistenceContext(unitName = "org.imixs.workflow.jee.jpa")
    private EntityManager manager;

As the jpa-components.jar is now located in the /lib folder of the ear you need to declare the location of the jpa unit in the persistence.xml file. And now I am back to the my-ejb.jar module where you are the component-developer. As you control this module you can place the persistence.xml file into the META-INF folder and define the location of your jpa-component.jar there:

persistence.xml:

<persistence>
    <persistence-unit name="org.imixs.workflow.jee.jpa">
        <jta-data-source>jdbc/workflow-db</jta-data-source>
        <properties>
            <property name="toplink.ddl-generation"
                value="create-tables" />
        </properties>
        <jar-file>lib/jpa-components.jar</jar-file>
    </persistence-unit>
</persistence>

So again you have full control about the deployment of all your components provided by third party component-libraries.

CONCLUSION

After some problems starting deploying my EAR on Glassfish V3 (migrating from Glassfish V2.1) I think JEE6 is still a flexible and powerful application platform. Also the platform supports strong capabilities in the configuration of complex applications and the usage of third party components. And JEE6 is a component architecture which supports a modular concept of build applications from components to be reused in different situations.

But I still have some problems in deploying WebService components from a component-library. I will continue to figure out how to deploy such components. If you have any suggestions or comments please let me know and post them here.