[jBPM Users] - Re: JBPM 4.1 Blob issue on AS400 DB2
by irisjacky99
OK, after a lot of troubleshooting debugging. Finally find a solution for it. I really hope someone from JBPM team can comment on this.
Basically, the LobLocator won't work if I try to getBytes once the resultset is closed. This is because BlobStrategyBlob in JBPM has following method
public byte[] get(Lob lob) {
| if (lob.cachedBytes!=null) {
| return lob.cachedBytes;
| }
|
| java.sql.Blob sqlBlob = lob.blob;
| if (sqlBlob!=null) {
| try {
| return sqlBlob.getBytes(1, (int) sqlBlob.length());
| } catch (SQLException e) {
| throw new JbpmException("couldn't extract bytes out of blob", e);
| }
| }
| return null;
| }
The highlighted one is calling hibernate code, and then use the lob locator. If it is new deployment with the test, the cachedBytes is return, therefore, no problem.
When we start process from existing deployment. it call this.
log.trace("loading deployment "+deploymentId+" from db");
| DeploymentImpl deployment = (DeploymentImpl) session.load(DeploymentImpl.class, Long.parseLong(deploymentId));
| deployerManager.deploy(deployment);
| object = repositoryCache.get(deploymentId, objectName);
| if (object==null) {
| throw new JbpmException("deployment "+deploymentId+" doesn't contain object "+objectName);
| }
The highlighted code does the loading from db. But it will not load blob data and just have lob locator instead. Then the deployerManager.deploy(deployment);
will call the lob locator to get data. And it is not happy because the resultset is closed by then. Therefore, exception in the original post happened.
I finally get around it by specifying the jdbc properties
<prop key="lob threshold">1048576</prop>
View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4264917#4264917
Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4264917
16 years, 5 months
[jBPM Users] - Re: JBPM 4.1 Blob issue on AS400 DB2
by irisjacky99
Thanks, Robinthomas.
I did notice this issue on DB2, which will result in another sql exception, DataTruncationException. We fixed this one already. We didn't let JBPM hbm to generate tables. Instead, we use table script to create them. The length of the BLOB is 1048576 now.
In fact, the above code works when we use it in unit test extending AbstractTransactionalSpringJbpmTestCase when the deployment is created fresh with the start process. However, it won't work if we try to start a process already deployed in the database, even unit testing. Found a link seems to related to this.
http://www-01.ibm.com/support/docview.wss?uid=nas16b3919404d0b1c2a86256ed...
But upgrading jt400.jar doesn't solved the problem, already tried. Hibernate 3.3.2 documentation also says
anonymous wrote :
| clob, blob
|
| Type mappings for the JDBC classes java.sql.Clob and java.sql.Blob. These types can be inconvenient for some applications, since the blob or clob object cannot be reused outside of a transaction. Driver support is patchy and inconsistent.
|
I also debug the JBPM code. the getBytes() called outside the session.load() . Not sure it is related to the way JBPM is implemented just doesn't fit AS400 DB2. I tried to changed the behavior of transactions on JBPM, but there is little documentation talking about that. Only a little bit mentioned in the JBPM Dev Guide, talking about using SpringTransactionInterceptor. Our caller method of above code is already wrapped in the Required transaction. It should join the tx if JBPM is using required as well.
I am posting the whole jbpm config here in case someone can help.
| <?xml version="1.0" encoding="UTF-8"?>
|
| <jbpm-configuration>
|
| <import resource="jbpm.jpdl.cfg.xml" />
| <import resource="jbpm.identity.cfg.xml" />
| <import resource="jbpm.jobexecutor.cfg.xml" />
| <import resource="jbpm.businesscalendar.cfg.xml" />
| <process-engine-context>
| <repository-service />
| <repository-cache />
| <execution-service />
| <history-service />
| <management-service />
| <identity-service />
| <task-service />
|
| <!-- Here we needed to change the transaction interceptor -->
| <command-service>
| <retry-interceptor />
| <environment-interceptor />
| <spring-transaction-interceptor />
| </command-service>
|
| <!-- Added spring as read-context-->
| <script-manager default-expression-language="juel"
| default-script-language="juel"
| read-contexts="execution, environment, process-engine, spring"
| write-context="">
| <script-language name="juel"
| factory="org.jbpm.pvm.internal.script.JuelScriptEngineFactory" />
| </script-manager>
|
| <id-generator />
| <types resource="jbpm.variable.types.xml" />
|
| <address-resolver />
|
|
| <mail-template name='task-notification'>
| <to users="${task.assignee}"/>
| <subject>${task.name}</subject>
| <text><![CDATA[Hi ${task.assignee},
| Task "${task.name}" has been assigned to you.
| ${task.description}
|
| Sent by JBoss jBPM
| ]]></text>
| </mail-template>
|
| <mail-template name='task-reminder'>
| <to users="${task.assignee}"/>
| <subject>${task.name}</subject>
| <text><![CDATA[Hey ${task.assignee},
| Do not forget about task "${task.name}".
| ${task.description}
|
| Sent by JBoss jBPM
| ]]></text>
| </mail-template>
|
| </process-engine-context>
|
| <transaction-context>
| <repository-session />
| <db-session />
|
| <message-session />
| <timer-session />
| <history-session />
| <mail-session>
| <mail-server>
| <session-properties resource="jbpm.mail.properties" />
| </mail-server>
| </mail-session>
|
| <!--
| Need to set explicitly that we don't want jbpm to create sessions
| -->
| <hibernate-session current="true" />
| </transaction-context>
| </jbpm-configuration>
|
View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4264910#4264910
Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4264910
16 years, 5 months
[jBPM Users] - Re: Advice regarding complex proccess modeling
by saraswati.santanu
How about creating sub-tasks in you actual task? Signalling flag will be false for the sub-tasks by default. So it will not transit to the next node till you call complete on the super task.
The following code may be used when the review task becomes active
| Task reviewTask = taskService.createTaskQuery()
| .activityName("Review")
| .processInstanceId(processInstanceId)
| .uniqueResult();
|
| for (String userId:userIds) {
| TaskImpl subTask = reviewTask.createTask("Review for user "+userId)
| .addCandidateUser(userId);
|
| reviewTask.addSubTask(subTask);
| }
|
When an user performs review then you can execute something like this:
| //somehow get the review task
| Task reviewTask = taskService.createTaskQuery()
| .activityName("Review")
| .processInstanceId(processInstanceId)
| .uniqueResult();
|
| //some get the sub task for this user
| Task reviewSubTask = taskService.createTaskQuery()
| .activityName("Review for user "+userId)
| .processInstanceId(processInstanceId)
| .uniqueResult();
|
| //complete the sub task
| taskService.completeTask(reviewSubTask.getId());
|
| //remove sub task from the super task
| reviewTask.removeSubTask(reviewSubTask);
|
| //if there exists not sub task then move on
| if (reviewTask.getSubTasks().isEmpty()) {
| taskService.completeTask(reviewTask.getId());
| }
|
This is just an idea I got now. I have never tried this. So the code may not be accurate. Let me know if it works.
You may need to create a node altogether if you need to implement your own activity behaviour. You cannot really assign your own behaviour to the existing Task node of Jbpm. This also can be an approach to solve this problem.
View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4264867#4264867
Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4264867
16 years, 5 months
[jBPM Users] - Re: [jBPM 4.1] Process Definition XML File
by saraswati.santanu
Koen,
My two cents. All that people might need is a nice wrapper over a DOM API which makes Jpdl xml writing using Java code simpler. This may not really require to touch any of the core classes for this. For e.g. I can write something like:
| //this is the step where we generate the xml dynamically
| JpdlWriter writer = new JpdlWriter();
| String xmlString = writer.startNode("Start Node Name")
| .transition("Transition Name", "Next Task")
| .task("Next Task")
| ... etc.
| .xml();
|
| //this is deployment, which is the same even for a static xml, read from a file
| String deploymentId = repositoryService.createDeployment()
| .addResourceFromString(resourceName, xmlString)
| .deploy();
|
I would assume the JpdlWriter class and any other associated classes will not do anything with the real process definition object. However code above is just a random thought to elaborate the idea.
I believe something like this Sebastian suggested and you also mentioned.
View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4264858#4264858
Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4264858
16 years, 5 months