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 ... ;-)
Posted at 11:50AM Apr 18, 2010
Posted by: Ralph
Category: General
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.... ;-)
Posted at 09:36PM Dez 11, 2009
Posted by: Ralph
Category: General
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....
Posted at 06:24AM Jul 09, 2009
Posted by: Ralph
Category: General
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.
Posted at 11:51AM Apr 15, 2009
Posted by: Ralph
Category: General
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𿠥
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񀰯
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)
Posted at 11:10AM Jul 06, 2008
Posted by: Ralph
Category: General