Monday, November 5, 2007

jvm parameters while doing j2ee development

When doing j2ee development you redeploy a lot of war/ear archives. When using standard jvm settings this will result in OutOfMemory condtions and the famous PermGen space Exception.

I use following parameters for my jvm:


-XX:+UseConcMarkSweepGC -XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled
-XX:MaxPermSize=128m -Xms1024m -Xmx1024m -Dsun.rmi.dgc.client.gcInterval=3600000
-Dsun.rmi.dgc.server.gcInterval=3600000



See here for more information for a detailed explanation about some of these parameters ( especially for the Concurrent Mark Sweep garbage collector an permgen space issues.

You might want to set -Xms and -Xmx a little bit lower if you dont have that much ram available.

Friday, October 26, 2007

jboss seam and jbpm async nodes

In a jboss seam project i wanted to use async nodes in a jbpm workflow. You can add "async=true" to any node in you jbpm process definition. This makes the workflow continue in the background so your user interface does not have to wait for the complete workflow to complete.

I accomplished this by starting the JbpmThreadServlet by adding in the web.xml:


<!-- Jpbpm Thread listener which will do async continuations & Timer -->

<servlet>
<servlet-name>JbpmThreadsServlet</servlet-name>
<servlet-class>org.jbpm.web.JbpmThreadsServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JbpmThreadsServlet</servlet-name>
<url-pattern>/jbpmthreads</url-pattern>
</servlet-mapping>



When your web application starts, jbpm will spawn off a thread that will continue your workflow. This thread is also being used for sending out email notifications of task nodes.

A problem that rises here is that your action handlers don't have access to the seam contexts. To solve this problem I made a abstract action handler which will startup the seam lifecycle from a such an actionHandler if it does not exist. This code comes from the seam 2.0.0 framework which actually support this. I haven't tried it out still.

The code for the actionHandler is:



import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.contexts.Lifecycle;
import org.jboss.seam.core.BusinessProcess;
import org.jbpm.graph.def.ActionHandler;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.taskmgmt.exe.TaskInstance;

public abstract class SeamContextualActionHandler implements ActionHandler {

abstract public void executeInSeam(ExecutionContext context)
throws Exception;

public void execute(final ExecutionContext context) throws Exception {

try {
if (Contexts.isEventContextActive()
|| Contexts.isApplicationContextActive()) //not sure about the second bit (only needed at init time!)
{

} else {
Lifecycle.beginCall();
try {
initProcessAndTask(context);
executeInSeam(context);
} finally {
Lifecycle.endCall();
}
}
} catch (RuntimeException re) {
throw re;
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private static void initProcessAndTask(ExecutionContext context) {
BusinessProcess businessProcess = BusinessProcess.instance();
businessProcess.setProcessId(context.getProcessInstance().getId());
TaskInstance taskInstance = context.getTaskInstance();
if (taskInstance != null) {
businessProcess.setTaskId(taskInstance.getId());
}
}

}





Your actionHandlers should extend this class and implement the executeInSeam() method instead of the execute method from the ActionHandler interface.

Friday, October 19, 2007

Jboss Seam Jaas authentication and jbpm Actors

The Identity component in Seam is a pretty handy thing. You can authenticate users by providing your own Authentication method or you can use JAAS. At my company we prefer JAAS. However there is a catch. When you also use jbpm, you should be able to populate the Actor component. But because we use JAAS there is no direct way to execute some custom code.

Fortunatly the seam developers provide a event model. Several components can emit events which our code can Listen on. It is very simple. You can simply add the @Observer annotation to a method with the correct event.

Now for populating the Actor component, we are going to write a Observer that listens to the "org.jboss.seam.postAuthenticate" event. You can read about these events in the seam documentation.

The next problem is that the JAAS API completely sucks. It is easy to find out if the users is in a specific role, but finding all the roles a user has is not possible. Fortunatly i found some code on the seam forums from a clever guy that allows me to do it. The drawback is that you make your code container specific. But for the moment being it serves me well.

So my authentication handler looks like this now:


import java.util.Enumeration;
import java.util.Iterator;

import javax.security.auth.Subject;

import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Observer;
import org.jboss.seam.core.Actor;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.Identity;
import org.jboss.security.SimpleGroup;
import org.jboss.security.SimplePrincipal;

@Name("postAuthenticationHandler")
public class PostAuthenticationHandler {

@Logger
Log log;

@In
Identity identity;

@In
Actor actor;

@SuppressWarnings("unchecked")
@Observer("org.jboss.seam.postAuthenticate")
public void doPostAuthenticate() {
log.info("Entering doPostAuthenticate...");
actor.setId(identity.getUsername());
Subject subject = identity.getSubject();

Iterator principleItr = subject.getPrincipals().iterator();
while (principleItr.hasNext()) {
Object principle = principleItr.next();
if (principle instanceof SimpleGroup) {
SimpleGroup simpleGroup = (SimpleGroup) principle;
Enumeration simpleGroupMembers = simpleGroup.members();
while (simpleGroupMembers.hasMoreElements()) {
Object o = simpleGroupMembers.nextElement();
SimplePrincipal aPrincipal = (SimplePrincipal) o;
log.info ("User " + identity.getUsername() + " is a member of group " + aPrincipal.getName());
actor.getGroupActorIds().add(aPrincipal.getName());
}
}
}
}
}


So first we inject the Actor/Identity components. Also notice the @Observer annotation which causes this method to be invoked when the postAuthenticate event is raised.

In the method itself we will get the JAAS subject from the identity component. This Subject class is some kind of container which contains all authentication specific attributes for this users called Principals. Now we can iterate over these Principals and extract the roles from it and insert them into the Actor component. As you see we cast the principle to a SimpleGroup which is a jboss specific implementation. So deploying this code on something other than jboss or even on another version of jboss than version 4.0.5.GA will break this code. But i found no other way to get to this information otherwise.

Monday, October 15, 2007

postgresql and jdbc/hibernate batch updates

A thing I always forget is to turn of batch updates when using postgresql db. Postgresql is a nice open source SQL database. It is less known then mysql but it offers true ACID semantics. Anyway, it is my favorite choice for RDBMS. But you need to turn off batch updates if you are using hibernate or JPA ( which is also implemented by hibernate ). So make sure you turn it off with the property

hibernate.jdbc.batch_size and set the value to 0.

Otherwise you get an exception sounding like:


09:00:46,017 ERROR [AbstractFlushingEventListener] Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:249)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:139)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:515)
at org.jboss.tm.TransactionImpl.doBeforeCompletion(TransactionImpl.java:1491)
at org.jboss.tm.TransactionImpl.beforePrepare(TransactionImpl.java:1110)
at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:324)
at org.jboss.tm.TxManager.commit(TxManager.java:240)
...

Friday, October 12, 2007

accessing private fields

Today I learned again something new from the java reflection API. You can set private fields in a class. This comes in handy when you want to write a Unit test for a class that depends om some external services or classes;

Lets say we have:


public class ClassUnderTest {

private OtherClass otherClass;

public doSomethingWithOtherClass() {

otherClass.someFunction()
}
}


When we want to test this class we might want to Mock the OtherClass because we are not interested in the functionality of the otherClass. Our testcase has no direct access to the otherClass field so we need to use some magic to do so.

public class MyTestCase {
@Test
public void testDoSomethingWithOtherClass {
Field otherClassField = ClassUnderTest.class.getDeclaredField("otherClass"); (1)
otherClassField.setAccessible(true); (2)

ClassUnderTest classUnderTest = new ClassUnderTest();
OtherClass otherClass = createMock(OtherClass.class);
otherClass.someFunction();
otherClassField.set(classUnderTest,otherClass); (3)
replay(otherClass)
classUnderTest.doSomethingWithOtherClass();
verify(otherClass);

}
}


(1) We use the reflection api to fetch the private Field of the ClassUnderTest
(2) We make it accessible
(3) We set the value on a instance of ClassUnderTest

And we're set.

createMock() replay() and verify() are functions from EasyMock which is a verify nice framework for creating Mock objects. You should certainly take a look at it if you don't know it yet. @Test is a annotation from testng unit test framework.



Wednesday, October 3, 2007

Itil open books

I stumbled this evening on a interesting site: http://www.itlibrary.org/ For the real ITIL books you have to pay lots of money, but here you will find a free view on all itil processes. Another thing that catched my attention was the faq. I want to quote a little piece of this faq I find personally extremely important:


ITIL books emphasise that organisations that have succeeded in implementing ITIL have one important thing in common - a strong 'Executive Sponsor'. This means a senior manager - ideally on the Board of Directors, the Corporate Information Officer or some similarly important role - is passionate about ITIL being implemented. When conflicts arise (as they do), the Sponsor will champion the cause, making sure the ITIL project has the funding and the authority to succeed.

This is the most important thing for a successfull implementation i think.


Tuesday, October 2, 2007

jboss seam and jbpm in a message driven bean hell

Hi all,


Last friday i was struggling with the bijection stuff of jboss seam. Bijection allows you to inject and outject variables to the several contexts jboss seam offers.

What i am trying to do is to create a jbpm process from a message driven bean and 'outject' some variables to the business context. I want to inject these same variables in a action handler when the business process enters a node. But things go wrong here. Actually things go already wrong when creating the jbpm process. I found a bugreport on the jboss bug tracking system that creating a jbpm process within a message driven bean does not work, so i suspect saving these variables to it has also something to do with it.

My code is very simple:

@CreateProcess(definition="inkless")
public void onMessage(Message m){
//some Message Parsing goes here
}
But i get lots of transaction related exeptions here. I found the following jira issue:
http://jira.jboss.org/jira/browse/JBSEAM-798 and related forum thread at http://www.jboss.com/index.html?module=bb&op=viewtopic&t=101047


I think my next step will be to check out jboss seam 2.0.0 CR1.

Wednesday, September 12, 2007

Could not enlist in transaction on entering meta-aware object!

This errormessage provided by the Jboss j2ee server gave me a major headance. In a project we are using 2 datasources:

  • an oracle datasource being used by iBatis DAO layer
  • a postgresql datasource being used by JPA DAO layer
After invoking both DAO layers I got this nice SystemException by the JTA transactionmanager.

Investigation showed me ( a few hours later ) that the oracle datasource is not XA by default. You have to configure it to use the XADataSource. You can find a example in the jboss distribution in docs/examples/jca/oracle-xa-ds.xml