Friday Jul 01, 2011

Disabling Glassfish-specific (Non-portable) JNDI names

Today I run into a problem with my EJB 3.1 application after I tried to deploy more than one app with the same EJB module on the same glassfish domain. This results in a JNDI-Naming conflict telling you, that the EJB name is already bound. But since the new concept of JEE6 global portable jndi names this should not happen? 

Here is a discussion about the problem: http://home.java.net/node/702307

The solution is quite simple as Glassfish provides a new property to disable the generation of the glassfish-specific non-portable  jndi names (which were only provided because of backward compatibility. Simply add the param 'disable-nonportable-jndi-names' with the value 'true' directly into the EJB-Container additional-property section. This will avoid the create of thus names.

See also the following pages for more deails about this topic:

http://download.oracle.com/docs/cd/E18930_01/html/821-2417/gkhtw.html

http://download.oracle.com/docs/cd/E18930_01/html/821-2418/beanx.html#gkndi

http://download.oracle.com/docs/cd/E18930_01/html/821-2416/gglpq.html


Sunday Apr 18, 2010

EJB 3.0 and WebServices

If you are interesting in programming EJB 3.0 (JEE5 / JEE6) you may be also try to implement a web service. Developing WebServices in JEE5 is not so hard. There are a lot of good books about all this stuff. I spent a lot of time the last two years in developing JEE5 WebServices.

But now after I started to migrate the Imixs Workfow Project  to Glassfish 3 I run into a lot of problems. And today I found out that there is a really big trap where I stumbled into.

In most of the JEE5 EJB/WebService examples you learn to annotate simply your stateless session ejb with the @webservice annotation to generate a new web service. So these examples combine EJB and Webservice in one implementation. The code result cann look something like this:

 .....
@DeclareRoles( { "myrole1",
        "myrole2" })
@RolesAllowed( { "myrole1" })
@Stateless
@Remote(org.imixs.workflow.jee.ws.WorkflowWebService.class)
@WebService(name = "WorkflowManagerService", targetNamespace = "http://imixs.org/workflow/services", serviceName = "WorkflowManagerService", portName = "WorkflowManagerServicePort", wsdlLocation = "ix_workflowservice.wsdl")
public class WorkflowWebServiceBean implements
        WorkflowWebService {

    @EJB
    SomeServiceEJB myService;
....

    @WebMethod
    public Entity myMethod(@WebParam(name = "workitemid", mode = Mode.IN)String uniqueid)
            throws Exception {
        ....
    }
....

This is a code snippet out of the Imixs workflow project which works very well in Glassfish 2.1.
At the end the combination of @Stateless and @WebService annotations looks interesting but I dissuade you to do so! You may run into a lot of problems make it hard to get a platform independent ejb code. The reason is that you are forced to provide a lot of application server specific deployment configuration in your descriptors. For example in Glassfish you have to define the authentifcation method in the sun-ejb-jar.xml. Also providing wsdl files is not so easy as they are now mixed with your ejb code. This seems to be mostly a problem for JEE6 / Glassfish 3. I run into these problems when I tried to deploy my bullet proved code from Glassfish 2.1 on Glassfish 3 or JBoss 5. JEE6 makes things easier and the goal should be to move away as many declarations in source code as possible.

So at the end my recommendation is to saperate allways(!) the web service implementation from the EJB module. Do not bundle stateless session ejbs together with webservices in a JEE EJB 3.0 module. The best way seems to be to implement the webservice classes (those classes which use the @WebSerivce annotation) in a web module. You can simply add this web module to you ear package to make use of EJB code like I do in my code example above. This will work in JEE5 (Glassfish 2.1) as well as in JEE6 (Glassfish 3).

And finally if you separate your code in different modules you can kick the webservice module if you do not need it in your application. In most cases web services are long-winded code. Better work with REST services ... ;-)

Friday Dec 11, 2009

JEE5 EAR EJB Deplyoment

Today I found this wunderfull article about EJB Deploymen tin JEE5:

http://www.developer.com/java/ejb/article.php/10931_3670496_1/Packaging-EJB-3-Applications.htm

I think this article is helpfully for anyone how struggles with deployment strategies in JEE5 EARs.

I do this fight currently as I try to find out the best way to deploy the Imixs JEE Worklfow components in an enterprise application.... ;-)


 

 

Thursday Jul 09, 2009

Glassfish TimerService - Expunging timer after failed deliveries

On my glassfish installation I am running different TimerServices. In one I saw the problem that the TimerService stopped unexpected after running more than 20 hours. 

In this situations a exeption is logged by the server like this one:

[#|2009-07-09T03:10:56.375+0200|INFO|sun-appserver2.1|javax.enterprise.system.container.ejb|_ThreadID=15;_ThreadName=p: thread-pool-1; w: 4;'1@@1247059844937@@server@@domain1' 'TimedObject = ScheduledWorkflowServiceImplementation' 'Application = myapp.ear-1.3.4' 'BEING_DELIVERED' 'PERIODIC' 'Container ID = 81721584505847814' 'Wed Jul 08 15:30:44 CEST 2009' '600000' ;2;|EJB5119:Expunging timer ['1@@1247059844937@@server@@domain1' 'TimedObject = ScheduledWorkflowServiceImplementation' 'Application = myapp.ear-1.3.4' 'BEING_DELIVERED' 'PERIODIC' 'Container ID = 81721584505847814' 'Wed Jul 08 15:30:44 CEST 2009' '600000' ] after [2] failed deliveries|#]

There is a Bugreport concerning this issue:

https://glassfish.dev.java.net/issues/show_bug.cgi?id=4634

and also this discussion thread:

http://forums.java.net/jive/thread.jspa?messageID=219367

arround this toppic.

Now I will test if changing the TimerService settings in the EJB Containterconfiguration will solve the problem.

First I will change the following Params

  • "Maximum Redeliveries" from "1" -> "16"
  • "Redelivery Interval" from 5000 -> 30000

 not sure if this will help....


Wednesday Apr 15, 2009

Using @runas in EJB 3.0

Today I implemented a EJB where I used the @runas annotation the first time.

This annotation allows you to skip over the security settings in your EJB module. I use the Imixs IX JEE Workflow so I have to deal with the workflow IX Workflow roles. My new EJB should create a new workflow task triggered by a not authenticated user (anonymous). So my EJB need the workflow role "org.imixs.ACCESSLEVEL.AUTHORACCESS" to get access to the workflow model and the grant to create a new workitem. This can be decleared by the @runas annotation in the EJB implemenation


package org.imixs.business;

....
@Stateless
@DeclareRoles( { "org.imixs.ACCESSLEVEL.AUTHORACCESS" })
@RunAs("org.imixs.ACCESSLEVEL.AUTHORACCESS")
public class ContactServiceBean implements ContactService {

// Workflow Manager
@EJB
org.imixs.workflow.jee.ejb.WorkflowManager wm;
ItemCollection workItem = null;

/**
* This method creates a new Contact worktiem.
*/
public ItemCollection create() throws Exception {
// create emtpy workitem
workItem = wm.createWorkItem(INITIAL_PROCESS);
workItem.replaceItemValue("type", "contact");
return workItem;
}
.....
}

Next it is necessary (I am running on Glassfish server) to add a User Principal to the sun-ejb-jar.xml and also declare the pricipal:

sun-ejb-jar.xml:

 

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 EJB 3.0//EN" "http://www.sun.com/software/appserver/dtds/sun-ejb-jar_3_0-0.dtd">
<sun-ejb-jar>
<security-role-mapping>
<role-name>org.imixs.ACCESSLEVEL.READERACCESS</role-name>
<principal-name>org.imixs.ACCESSLEVEL.READERACCESS</principal-name>
</security-role-mapping>
<security-role-mapping>
<role-name>org.imixs.ACCESSLEVEL.AUTHORACCESS</role-name>
<principal-name>org.imixs.ACCESSLEVEL.AUTHORACCESS</principal-name>
</security-role-mapping>
<security-role-mapping>
<role-name>org.imixs.ACCESSLEVEL.EDITORACCESS</role-name>
<principal-name>org.imixs.ACCESSLEVEL.EDITORACCESS</principal-name>
</security-role-mapping>
<security-role-mapping>
<role-name>org.imixs.ACCESSLEVEL.MANAGERACCESS</role-name>
<group-name>IMIXS-WORKFLOW-Manager</group-name>
<principal-name>WorkflowScheduler</principal-name>
</security-role-mapping>
<enterprise-beans>
<ejb>
<ejb-name>ContactServiceBean</ejb-name>
<jndi-name>ejb/ShareyourworkContactServiceBean</jndi-name>
<principal><name>WorkflowScheduler</name></principal>
</ejb>
</enterprise-beans>
</sun-ejb-jar>


Now the principal "WorkflowScheduler" is named as a principal in my EJB declaration and is mapped to the role "org.imixs.ACCESSLEVEL.MANAGERACCESS" this user will be able to call my EJB methods. As this role is declared as a @runas role in my contactEJB the principal "WorkflowScheduler" will be used by the EJB container to run the methods in my ejb.


Sunday Jul 06, 2008

using JNDI MailSession in Glassfish

Today I played around a long time figuring out how to lookup a Java Mail Session out of a EJB from Glassfish. This is the link which finaly helps me through:

http://forums.java.net/jive/thread.jspa?messageID=260133&#260133

before I read a lot of pages like:

https://glassfish.dev.java.net/javaee5/docs/DG/beaow.html

http://forums.java.net/jive/thread.jspa?messageID=265263&#265263

The problem for me was the lookup like thisone:

 Context ic = new InitialContext();
Session session = (Session)ic.lookup("java:comp/env/mail/testSession");

 To avoid a :

javax.naming.NameNotFoundException: No object bound to name java:comp/env/mail/testSession

 it is importend to add the right name mapping to the ejb-jar.xml and also to the sun-ejb-jar.xml

to the ejb-jar.xml add the following code to that EJB which makes the lookup:        

    <resource-ref>
        <res-ref-name>mail/testSession</res-ref-name>
        <res-type>javax.mail.Session</res-type>
        <res-auth>Container</res-auth>
        <res-sharing-scope>Shareable</res-sharing-scope>
    </resource-ref>

And to the sun-ejb-jar.xml file add the following to the same EJB

 <resource-ref>
        <res-ref-name>mail/testSession</res-ref-name>
        <jndi-name>testSession</jndi-name>
 </resource-ref>

Notice that this is only necessary to perform a jndi lookup. I think you can save oneself this using dependency injection using annotations (@ressource)