[jboss-user] [JBoss jBPM] - Strange class cast exception when changing node assignment

ij_dett do-not-reply at jboss.com
Wed Mar 7 08:25:02 EST 2007


Hello folks,

I discovered a strange class cast exception when evaluating jBPM and its starter kit. My team and me want to use jBPM in a scenario where the workflow engine is controlling other external processes.

Due to certain project requirements we need to extend the functionality of class org.jbpm.graph.def.Node by subclassing it. Following the jBPM documentation I applied the necesarry changes to the sources in the starter kit, rebuilded and redeployed the jBPM service archive and the web application.

Here are the steps I performed:

Step 1: Changed file jbpm.cfg.xml to reference a different node types mapping file

  | <jbpm-configuration>
  | 
  |   <!-- 
  |     This configuration is used when there is no jbpm.cfg.xml file found in the 
  |     root of the classpath.  It is a very basic configuration without persistence
  |     and message services.  Only the authorization service installed.
  |     You can parse and create processes, but when you try to use one of the 
  |     unavailable services, you'll get an exception.
  |   -->
  |   
  |   <jbpm-context>
  |     <service name="persistence" factory="org.jbpm.persistence.db.DbPersistenceServiceFactory" />
  |     <service name="message" factory="org.jbpm.msg.db.DbMessageServiceFactory" />
  |     <service name="scheduler" factory="org.jbpm.scheduler.db.DbSchedulerServiceFactory" />
  |     <service name="logging" factory="org.jbpm.logging.db.DbLoggingServiceFactory" />
  |     <service name="authentication" factory="org.jbpm.security.authentication.DefaultAuthenticationServiceFactory" />
  |   </jbpm-context>
  | 
  |   <!-- configuration resource files pointing to default configuration files in jbpm-{version}.jar -->
  |   <string name="resource.hibernate.cfg.xml" value="hibernate.cfg.xml" />
  |   <string name="resource.business.calendar" value="org/jbpm/calendar/jbpm.business.calendar.properties" />
  |   <string name="resource.default.modules" value="org/jbpm/graph/def/jbpm.default.modules.properties" />
  |   <string name="resource.converter" value="org/jbpm/db/hibernate/jbpm.converter.properties" />
  |   <string name="resource.action.types" value="org/jbpm/graph/action/action.types.xml" />
  |   <string name="resource.node.types" value="de/webde/geppi/node.types.xml" />
  |   <string name="resource.parsers" value="org/jbpm/jpdl/par/jbpm.parsers.xml" />
  |   <string name="resource.varmapping" value="org/jbpm/context/exe/jbpm.varmapping.xml" />
  | 
  |   <long   name="jbpm.msg.wait.timout" value="5000" singleton="true" />
  |   <int    name="jbpm.byte.block.size" value="1024" singleton="true" />
  |   <string name="mail.smtp.host" value="localhost" />
  |   <bean   name="jbpm.task.instance.factory" class="org.jbpm.taskmgmt.impl.DefaultTaskInstanceFactoryImpl" singleton="true" />
  |   <bean   name="jbpm.variable.resolver" class="org.jbpm.jpdl.el.impl.JbpmVariableResolver" singleton="true" />
  |   <bean   name="jbpm.mail.address.resolver" class="org.jbpm.identity.mail.IdentityAddressResolver" singleton="true" />
  | 
  | </jbpm-configuration>
  | 

The important line is

  | <string name="resource.action.types" value="org/jbpm/graph/action/action.types.xml" />
  | 

Step 2: Added the alternative node mapping configuration

  | <node-types>
  |   <node-type element="start-state" class="org.jbpm.graph.node.StartState" />
  |   <node-type element="end-state" class="org.jbpm.graph.node.EndState" />
  |   <node-type element="node" class="de.webde.geppi.GeppiNode" />
  |   <node-type element="state" class="org.jbpm.graph.node.State" />
  |   <node-type element="task-node" class="org.jbpm.graph.node.TaskNode" />
  |   <node-type element="fork" class="org.jbpm.graph.node.Fork" />
  |   <node-type element="join" class="org.jbpm.graph.node.Join" />
  |   <node-type element="decision" class="org.jbpm.graph.node.Decision" />
  |   <node-type element="process-state" class="org.jbpm.graph.node.ProcessState" />
  |   <node-type element="super-state" class="org.jbpm.graph.def.SuperState" />
  |   <node-type element="merge" class="org.jbpm.graph.node.Merge" />
  |   <node-type element="milestone-node" class="org.jbpm.graph.node.MilestoneNode" />
  |   <node-type element="interleave-start" class="org.jbpm.graph.node.InterleaveStart" />
  |   <node-type element="interleave-end" class="org.jbpm.graph.node.InterleaveEnd" />
  |   <node-type element="page" class="org.jboss.seam.pageflow.Page" />
  |   <node-type element="start-page" class="org.jboss.seam.pageflow.Page" />
  | </node-types>
  | 

The important line switching the implementation from class org.jbpm.graph.def.Node to class de.webde.geppi.GeppiNode (Geppi is the system under development) is

  |   <node-type element="node" class="de.webde.geppi.GeppiNode" />
  | 

Step 3: Implemented class de.webde.geppi.GeppiNode and its corresponding hibernate ORM configuration file. 

Besides some additional console printing the current implementation of class de.webde.geppi.GeppiNode does not do anything different than class org.jbpm.graph.def.Node. The functional extension will be done later.

  | /**
  |  * 
  |  */
  | package de.webde.geppi;
  | 
  | import org.jbpm.graph.def.Node;
  | import org.jbpm.graph.exe.ExecutionContext;
  | 
  | /**
  |  * 
  |  */
  | public class GeppiNode extends Node {
  | 
  | 	/**
  | 	 * 
  | 	 */
  | 	private static final long serialVersionUID = -3137521269855001903L;
  | 
  | 	/* (non-Javadoc)
  | 	 * @see org.jbpm.graph.def.Node#execute(org.jbpm.graph.exe.ExecutionContext)
  | 	 */
  | 	public void execute(ExecutionContext executionContext) {
  | 		// if there is a custom action associated with this node
  | 		if (action != null) {
  | 			try {
  | 				System.out.println("+++++++++++++ Execute Action  +++++++++++++");
  | 				// execute the action
  | 				action.execute(executionContext);
  | 				System.out.println("+++++++++++++ Finished Action +++++++++++++");
  | 
  | 			} catch (Exception exception) {
  | 				// NOTE that Error's are not caught because that might halt the
  | 				// JVM and mask the original Error.
  | 				// search for an exception handler or throw to the client
  | 				raiseException(exception, executionContext);
  | 			}
  | 
  | 		} else {
  | 			// let this node handle the token
  | 			// the default behaviour is to leave the node over the default
  | 			// transition.
  | 			leave(executionContext);
  | 		}
  | 	}
  | 
  | }
  | 

  | <?xml version="1.0"?>
  | <!DOCTYPE hibernate-mapping PUBLIC
  |       "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  |           "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  | 
  | <hibernate-mapping default-access="field" >
  |   <subclass name="de.webde.geppi.GeppiNode" 
  |             discriminator-value="G" 
  |             extends="org.jbpm.graph.def.Node"/>
  | </hibernate-mapping>
  | 

Step 4: Updated the Hibernate configuration to include a mapping for class de.webde.geppi.GeppiNode 

  | <?xml version='1.0' encoding='utf-8'?>
  | 
  | <!DOCTYPE hibernate-configuration PUBLIC
  |           "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
  |           "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
  | 
  | <hibernate-configuration>
  |   <session-factory>
  | 
  |     <!-- jdbc connection properties -->
  |     <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
  |     <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
  |     <property name="hibernate.connection.url">jdbc:hsqldb:mem:.;sql.enforce_strict_size=true</property>
  |     <property name="hibernate.connection.username">sa</property>
  |     <property name="hibernate.connection.password"></property>
  | 
  |     <property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
  |         
  |     <!-- other hibernate properties 
  |     <property name="hibernate.show_sql">true</property>
  |     <property name="hibernate.format_sql">true</property>
  |     <property name="hibernate.use_sql_comments">true</property>
  |     -->
  | 
  |     <!-- ############################################ -->
  |     <!-- # mapping files with external dependencies # -->
  |     <!-- ############################################ -->
  | 
  |     <!-- following mapping file has a dependendy on   -->
  |     <!-- 'bsh-{version}.jar'.                         -->
  |     <!-- uncomment this if you don't have bsh on your -->
  |     <!-- classpath.  you won't be able to use the     -->
  |     <!-- script element in process definition files   -->
  |     <mapping resource="org/jbpm/graph/action/Script.hbm.xml"/>
  | 
  |     <!-- following mapping files have a dependendy on  -->
  |     <!-- 'jbpm-identity-{version}.jar', mapping files  -->
  |     <!-- of the pluggable jbpm identity component.     -->
  |     <!-- comment out the following 3 lines if you don't-->
  |     <!-- want to use the default jBPM identity mgmgt   -->
  |     <!-- component                                     -->
  |     <mapping resource="org/jbpm/identity/User.hbm.xml"/>
  |     <mapping resource="org/jbpm/identity/Group.hbm.xml"/>
  |     <mapping resource="org/jbpm/identity/Membership.hbm.xml"/>
  | 
  |     <!-- ###################### -->
  |     <!-- # jbpm mapping files # -->
  |     <!-- ###################### -->
  | 
  |     <!-- hql queries and type defs -->
  |     <mapping resource="org/jbpm/db/hibernate.queries.hbm.xml" />
  |     
  |     <!-- graph.def mapping files -->
  |     <mapping resource="org/jbpm/graph/def/ProcessDefinition.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/def/Node.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/def/Transition.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/def/Event.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/def/Action.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/def/SuperState.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/def/ExceptionHandler.hbm.xml"/>
  |     <mapping resource="org/jbpm/instantiation/Delegation.hbm.xml"/>
  | 
  |     <!-- Geppi mapping files -->
  |     <mapping resource="de/webde/geppi/GeppiNode.hbm.xml"/>
  |     
  |     
  |     <!-- graph.node mapping files -->
  |     <mapping resource="org/jbpm/graph/node/StartState.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/node/EndState.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/node/ProcessState.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/node/Decision.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/node/Fork.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/node/Join.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/node/State.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/node/TaskNode.hbm.xml"/>
  |     
  |     <!-- context.def mapping files -->
  |     <mapping resource="org/jbpm/context/def/ContextDefinition.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/def/VariableAccess.hbm.xml"/>
  | 
  |     <!-- taskmgmt.def mapping files -->
  |     <mapping resource="org/jbpm/taskmgmt/def/TaskMgmtDefinition.hbm.xml"/>
  |     <mapping resource="org/jbpm/taskmgmt/def/Swimlane.hbm.xml"/>
  |     <mapping resource="org/jbpm/taskmgmt/def/Task.hbm.xml"/>
  |     <mapping resource="org/jbpm/taskmgmt/def/TaskController.hbm.xml"/>
  | 
  |     <!-- module.def mapping files -->
  |     <mapping resource="org/jbpm/module/def/ModuleDefinition.hbm.xml"/>
  | 
  |     <!-- bytes mapping files -->
  |     <mapping resource="org/jbpm/bytes/ByteArray.hbm.xml"/>
  | 
  |     <!-- file.def mapping files -->
  |     <mapping resource="org/jbpm/file/def/FileDefinition.hbm.xml"/>
  | 
  |     <!-- scheduler.def mapping files -->
  |     <mapping resource="org/jbpm/scheduler/def/CreateTimerAction.hbm.xml"/>
  |     <mapping resource="org/jbpm/scheduler/def/CancelTimerAction.hbm.xml"/>
  | 
  |     <!-- graph.exe mapping files -->
  |     <mapping resource="org/jbpm/graph/exe/Comment.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/exe/ProcessInstance.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/exe/Token.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/exe/RuntimeAction.hbm.xml"/>
  | 
  |     <!-- module.exe mapping files -->
  |     <mapping resource="org/jbpm/module/exe/ModuleInstance.hbm.xml"/>
  |         
  |     <!-- context.exe mapping files -->
  |     <mapping resource="org/jbpm/context/exe/ContextInstance.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/exe/TokenVariableMap.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/exe/VariableInstance.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/exe/variableinstance/ByteArrayInstance.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/exe/variableinstance/DateInstance.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/exe/variableinstance/DoubleInstance.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/exe/variableinstance/HibernateLongInstance.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/exe/variableinstance/HibernateStringInstance.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/exe/variableinstance/LongInstance.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/exe/variableinstance/NullInstance.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/exe/variableinstance/StringInstance.hbm.xml"/>
  | 
  |     <!-- msg.db mapping files -->
  |     <mapping resource="org/jbpm/msg/Message.hbm.xml"/>
  |     <mapping resource="org/jbpm/msg/db/TextMessage.hbm.xml"/>
  |     <mapping resource="org/jbpm/command/ExecuteActionCommand.hbm.xml"/>
  |     <mapping resource="org/jbpm/command/ExecuteNodeCommand.hbm.xml"/>
  |     <mapping resource="org/jbpm/command/SignalCommand.hbm.xml"/>
  |     <mapping resource="org/jbpm/command/TaskInstanceEndCommand.hbm.xml"/>
  | 
  |     <!-- taskmgmt.exe mapping files -->
  |     <mapping resource="org/jbpm/taskmgmt/exe/TaskMgmtInstance.hbm.xml"/>
  |     <mapping resource="org/jbpm/taskmgmt/exe/TaskInstance.hbm.xml"/>
  |     <mapping resource="org/jbpm/taskmgmt/exe/PooledActor.hbm.xml"/>
  |     <mapping resource="org/jbpm/taskmgmt/exe/SwimlaneInstance.hbm.xml"/>
  | 
  |     <!-- scheduler.exe mapping files -->
  |     <mapping resource="org/jbpm/scheduler/exe/Timer.hbm.xml"/>
  | 
  |     <!-- logging mapping files -->
  |     <mapping resource="org/jbpm/logging/log/ProcessLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/logging/log/MessageLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/logging/log/CompositeLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/log/ActionLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/log/NodeLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/log/ProcessInstanceCreateLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/log/ProcessInstanceEndLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/log/ProcessStateLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/log/SignalLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/log/TokenCreateLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/log/TokenEndLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/graph/log/TransitionLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/log/VariableLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/log/VariableCreateLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/log/VariableDeleteLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/log/VariableUpdateLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/log/variableinstance/ByteArrayUpdateLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/log/variableinstance/DateUpdateLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/log/variableinstance/DoubleUpdateLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/log/variableinstance/HibernateLongUpdateLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/log/variableinstance/HibernateStringUpdateLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/log/variableinstance/LongUpdateLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/context/log/variableinstance/StringUpdateLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/taskmgmt/log/TaskLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/taskmgmt/log/TaskCreateLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/taskmgmt/log/TaskAssignLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/taskmgmt/log/TaskEndLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/taskmgmt/log/SwimlaneLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/taskmgmt/log/SwimlaneCreateLog.hbm.xml"/>
  |     <mapping resource="org/jbpm/taskmgmt/log/SwimlaneAssignLog.hbm.xml"/>
  |     
  |   </session-factory>
  | </hibernate-configuration>
  | 

The lines adding the additional mapping are

  |     <!-- Geppi mapping files -->
  |     <mapping resource="de/webde/geppi/GeppiNode.hbm.xml"/>
  | 
  | 

By the way, node.types.xml, GeppiNode.java and GeppiNode.hbm.xml were added in package de.webde.geppi in directory src/java.jbpm.

So far so good - Using the starter kits build file I could build and deploy the updated service archive.

But when starting the starter kit's JBoss I detected a strange error log on its console:

  | 13:57:26,300 INFO  [SchedulerThread] runtime exception while executing timers
  | org.hibernate.HibernateException: Could not parse configuration: hibernate.cfg.xml
  |         at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1494)
  |         at org.hibernate.cfg.Configuration.configure(Configuration.java:1428)
  |         at org.jbpm.db.hibernate.HibernateHelper.createConfiguration(HibernateHelper.java:90)
  |         at org.jbpm.persistence.db.DbPersistenceServiceFactory.getConfiguration(DbPersistenceServiceFactory.java:68)
  |         at org.jbpm.persistence.db.DbPersistenceServiceFactory.getSessionFactory(DbPersistenceServiceFactory.java:90)
  |         at org.jbpm.persistence.db.DbPersistenceService.getSessionFactory(DbPersistenceService.java:74)
  |         at org.jbpm.persistence.db.DbPersistenceService.getSession(DbPersistenceService.java:78)
  |         at org.jbpm.persistence.db.DbPersistenceService.getSchedulerSession(DbPersistenceService.java:254)
  |         at org.jbpm.JbpmContext.getSchedulerSession(JbpmContext.java:529)
  |         at org.jbpm.scheduler.impl.SchedulerThread.executeTimers(SchedulerThread.java:104)
  |         at org.jbpm.scheduler.impl.SchedulerThread.run(SchedulerThread.java:71)
  | Caused by: org.dom4j.DocumentException: org.dom4j.DocumentFactory Nested exception: org.dom4j.DocumentFactory
  |         at org.dom4j.io.SAXReader.read(SAXReader.java:484)
  |         at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1484)
  |         ... 10 more
  | 

To me a parsing exception looked odd since file hibernate.cfg.xml does not contain any syntax errors and the added line was correct.

To really find out what is going on I started a remote debugging session and discovered the following:

The root cause is a class cast exception I really do not understand:

  | ClassCastException: Cannot cast org.dom4j.DocumentFactory (id=169) to org.dom4j.DocumentFactory
  | 

It is originated in the static method getInstance() of class org.dom4j.DocumentFactory provided by the Dom4J library

  |     public static synchronized DocumentFactory getInstance() {
  |         if (singleton == null) {
  |             singleton = createSingleton();
  |         }
  |         return (DocumentFactory) singleton.instance();
  |     }
  | 

The class cast exception is thrown in the last line of this method. The stack trace looks like this:

  | Thread [JbpmCommandExecutor] (Suspended)	
  | 	DocumentFactory.getInstance() line: 97	
  | 	SAXReader.getDocumentFactory() line: 645	
  | 	SAXReader.createContentHandler(XMLReader) line: 969	
  | 	SAXReader.read(InputSource) line: 449	
  | 	Configuration.doConfigure(InputStream, String) line: 1484	
  | 	Configuration.configure(String) line: 1428	
  | 	HibernateHelper.createConfiguration(String, String) line: 90	
  | 	DbPersistenceServiceFactory.getConfiguration() line: 68	
  | 	DbPersistenceServiceFactory.getSessionFactory() line: 90	
  | 	DbPersistenceService.getSessionFactory() line: 74	
  | 	DbPersistenceService.getSession() line: 78	
  | 	DbPersistenceService.getMessagingSession() line: 245	
  | 	JbpmContext.getMessagingSession() line: 521	
  | 	DbMessageService.<init>() line: 49	
  | 	DbMessageServiceFactory.openService() line: 32	
  | 	Services.getService(String) line: 136	
  | 	Services.getMessageService() line: 172	
  | 	CommandExecutorThread.executeCommand() line: 122	
  | 	CommandExecutorThread.run() line: 83	
  | 

Does anybody have an idea what exactly is going on here?
IMHO I think I got trapped in JBoss' class loader hell, but currently I have no clue how to solve this issue. I know I am guessing, but ...

Any help and hints are appreciated ... Thanks in advance ...

Cheers,
Ingo

View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4025783#4025783

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4025783



More information about the jboss-user mailing list