Creating work item handler with a CDI producer and using CDI injection in handlers in jBPM

879 views
Skip to first unread message

Nenad Vukobratović

unread,
Jun 10, 2016, 3:40:28 PM6/10/16
to jBPM Usage
Hi,

I have a question with regards to using CDI in work item handlers in jBPM. In our BPM deployment, we have a META-INF/kie-deployment-descriptor.xml. It lists some work item handlers that are needed, among which there are two custom ones, i.e. our item handlers. Declaration of said handlers uses MVEL resolvers and they get created and associate with their respective processes. 

<work-item-handler>
<resolver>mvel</resolver>
<identifier>new com...LoadAppWorkItemhandlerImpl()</identifier>
<parameters />
<name>LoadAppService</name>
</work-item-handler>


When created this way however, I can't get any injection to happen. I finally understood that this was because my work item handlers are in fact not declared themselves as CDI beans, so nothing else will follow, as in fact @Inject annotations get ignored?

So I then wrote a producer to create my own work item handler, and at the same time annotate it with CDI annotations. My work item handler producer looks like this:

@ApplicationScoped
public class OgnWorkItemHandlerProducer implements WorkItemHandlerProducer {

@Inject
private DataManager dataManager;

@Override
public Map<String, WorkItemHandler> getWorkItemHandlers(String arg0, Map<String, Object> arg1) {
Map<String, WorkItemHandler> handlers = new HashMap<String, WorkItemHandler>();
LoadAppWorkItemhandlerImpl loadAppWorkItemHandler = new LoadAppWorkItemhandlerImpl();
loadAppWorkItemHandler.setDataManager(dataManager);
handlers.put("LoadAppService", loadAppWorkItemHandler);
return handlers;
}
}

What I want to achieve is to enable the injection of my data manager into the work item, so that if and when my handler gets invoked, I can use the data manager to access my database. So if I remove the declaration of the LoadAppWorkItemHandler from kie-deployment-descriptor.xml, the  BPM process invocation fails with an error that looks like this:

11:17:38,958 WARN  [org.kie.remote.services.cdi.ProcessRequestBean] (http-localhost/127.0.0.1:8080-6) Unable to execute StartProcessCommand/0: org.kie.remote.services.rest.exception.KieRemoteRestOperationException: 
[com...LoadAppProcess:1 - Load application:3] -- Could not find work item handler for LoadAppService
...
Caused by: org.jbpm.workflow.instance.WorkflowRuntimeException: [com...LoadAppProcess:1 - Load application:3] -- Could not find work item handler for LoadAppService
...
Caused by: org.drools.core.WorkItemHandlerNotFoundException: Could not find work item handler for LoadAppService


I interpret this as if the work item handler producer was not being called and the process not having a corresponding handler to handle the control over to? 

So I guess my question then is how do I trigger the invocation of my work item handler producer and get its injection points satisfied?  Just to rule out the obvious, I do have a beans.xml in my META-INF.

All help much appreciated.

Thanks,
Nenad

Maciej Swiderski

unread,
Jun 12, 2016, 5:55:31 AM6/12/16
to Nenad Vukobratović, jBPM Usage
the jar file with cdi work item handler producer must be on workbench classpath - meaning in jbpm-console.war/WEB-INF/lib so cdi container can find it. Once it’s there it shall be discovered and the provided for jBPM runtime. 

Are you sure that your handler producer is found?

Maciej
--
You received this message because you are subscribed to the Google Groups "jBPM Usage" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jbpm-usage+...@googlegroups.com.
To post to this group, send email to jbpm-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jbpm-usage/e4fe84e7-8f60-41a7-9451-cec7321b11a0%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Nenad A. Vukobratović

unread,
Jun 12, 2016, 6:00:39 PM6/12/16
to Maciej Swiderski, jBPM Usage
Hey Maciej,

Thanks for replying. I have ommitted two details that may come into play: 1) we are running on JBoss EAP 6.4.0 and jBPM 6.1.   2) we use curl to deploy our process jar with the following command line command:

curl -X POST -H "Authorization:Basic a2llQ2FsbGVyOmtpZUNhbGxlcjFAIw==" -v -w "\n\n" http://127.0.0.1:8080/business-central/rest/deployment/groupId:artifactId:%VERSION%/deploy

(where groupId and artifactId are respective values for our jar and come our maven build)

So not sure what you mean by the workbench, but we are deploying to business central. When I log into jBPM's admin console, under Deploy -> Process deployments, I see my jar deployed.

Now to answer your question, no, I don't think my CDI components and producer get discovered and initialized. In fact, I am sadly sure they don't get discovered. I can set a breakpoint in my handler and I can see that my CDI beans are null. And so far, I can only get my work item handler created if I supply a kie-deployment-descriptor.xml that declares my work item handler, like I mentioned, with a mvel resolver. The producer never gets invoked. If I comment out my work item handler in the kie descriptor, then I get a process with no handlers exception.

Further to that, under:

JBOSS_HOME/EAP-6.4.0/standalone/deployments

I see these three deployments: business-central.war, dashbuilder.war and kie-server.war.

So... am I deplying this incorrectly or to the wrong point, or with the wrong interface..?

Thanks,
Nenad



--
Stojanović Translating Services
http://www.sts-home.com
Prevodilačke Usluge Stojanović

Maciej Swiderski

unread,
Jun 13, 2016, 2:48:43 AM6/13/16
to "Nenad A. Vukobratović", jBPM Usage
You would need to package your CDI bean into valid bean arhive, meaning jar file with beans.xml inside META-INF folder. Then copy this jar into business-central.war/WEB-INF/lib folder. Once restarted handlers should be discovered. 

Maciej

Nenad Vukobratović

unread,
Jun 13, 2016, 3:11:50 PM6/13/16
to jBPM Usage, nenad.vuk...@gmail.com

Maciej, 

Tried doing that. I cannot help but think this might not be the how to deploy. Just to take few steps back and try to outline my project structure:

maven reactor project
 +-- config
 +-- api
      +-- service
      +-- ws
      +-- persistence
 +-- bpm
      +-- handlers
      +-- process
 +-- brm
 +-- model

So the persistence project is where all the fun begins. This is a JPA project, but to make things more interesting it uses spring-data-jpa. So I got all that wired up, the spring CDI extension activates, it creates the repositories where queries are defined, this binds to a datasource with corresponding drivers, and this all runs with an Arquilllian test, deployed as a war file onto a managed container (JBoss.7.1.1.Final).
Now the place where I actually want to use my JPA persistence is the handler project. So far, I have been using the restful deployment interface of business-central. The deployment is actuated with a batchfile, that, stepwise does this following:

1. deploy the web service war file (the ws project)
2. manipulate and store 2 properties file adminstrated with jboss-cli.bat
3. undeploy the brm module on the kie-server, and then deploy a new freshly built version using curl 
4. undeploy the process module on business-central, and the deploy a new freshly built version using curl

So note that the handler project is not deployed explicitly anywhere. I understand that this is handled as a maven dependency of the process project, through the restful deployment process. Like I said before however, when we deploy like this, the CDI constructs remain uninitialized and ignored. 

Now, I started following your recommendation. This required dropping not only my handlers jar with the CDI code (btw, it always had a beans.xml), but also a lot of dependency jars (all spring dependencies, all of our code that had a dependency) into the same business-central.war/WEB-INF/lib folder to make the classloader happy. This does not appear as a viable deployment approach and strategy. I mean, that *may* be ok for a local development environment, but when moving from one env to the next (QA, PROD etc..) this can hardly be sustainable. Is there not a different way to get CDI initialized in custom work item handlers? Additionally, it seems that the properties that are deployed as described above, are not available and visible when code dropped in the business-central/WEB-INF/lib folder runs.

Thanks,
Nenad

Maciej Swiderski

unread,
Jun 14, 2016, 4:27:09 AM6/14/16
to Nenad Vukobratović, jBPM Usage, nenad.vuk...@gmail.com
Alright, now all is clear. Kie server is not based on CDI so it does not support CDI work item handler producer. It is only supported in business central. 

Though I believe you could implement your own resolver used by deployment descriptor but it would still have to be put on classpath of kie server and not dependency of the kjar because CDI container is not aware of kjars and their dependencies. 

However you still have the same issue with updates as that will require restart of the app after changes to the jars in the app. 
Maybe then you can use another approach - let spring handle injections etc and the your handler looks up spring beans programatically. You would have to bind the application context somewhere (jndi, static holder) so handler can find it when initialized from deployment descriptor. Just an idea...

Maciej

Nenad Vukobratović

unread,
Jun 14, 2016, 10:20:07 AM6/14/16
to jBPM Usage, nvukob...@gmail.com, nenad.vuk...@gmail.com

Hi Maciej,

So I get a bit confused here. The component that we deploy to the kie-server are just the business rules (our BRM module with our .drl files). The BPM process jar gets deployed to business-central. My understanding is that through maven dependency resolution, the handlers jar also get deployed to ... business-central and not the kie-server? 

So when you say the kie server is not CDI based and hence does not support CDI, I get that, but remain deeply puzzled as to why that would be relevant since the handlers jar, I think?, is deployed in business central that *is* all CDI? We deploy our process jar with:
and that jar inside of it has maven dependency information, pom etc.. which includes, obviously the handlers jar version. 

The Spring approach is certainly interesting and worth exploring. But I thought given that business central is a CDI environment, that was the correct way to do it..?

Thoughts?

Thanks,
Nenad

Maciej Swiderski

unread,
Jun 14, 2016, 3:49:01 PM6/14/16
to Nenad Vukobratović, jBPM Usage, nenad.vuk...@gmail.com
Nenad,
On 14.06.2016, at 16:20, Nenad Vukobratović <nvukob...@gmail.com> wrote:


Hi Maciej,

So I get a bit confused here. The component that we deploy to the kie-server are just the business rules (our BRM module with our .drl files). The BPM process jar gets deployed to business-central. My understanding is that through maven dependency resolution, the handlers jar also get deployed to ... business-central and not the kie-server? 
I assume the kjar with rules only that is deployed to kie server does not have handler in the deps, right? Same for deployment descriptor, it’s not needed there if it’s rules based only.
Handlers should only be registered for kjars that do have processes otherwise they don’t make much sense.


So when you say the kie server is not CDI based and hence does not support CDI, I get that, but remain deeply puzzled as to why that would be relevant since the handlers jar, I think?, is deployed in business central that *is* all CDI?
business central is CDI but keep in mind that cdi container scans jars available on appliation boot time meaning jars that are in WEB-INF/lib of the app. Since your handlers are attached as kjar dependency it’s not visible to cdi container thus not discoved at all.

We deploy our process jar with:
and that jar inside of it has maven dependency information, pom etc.. which includes, obviously the handlers jar version. 
then cdi container is not involed in that deployment so it’s obvious it won’t discover it. CDI container is bound to JEE application life cycle and not kie (kjar) life cycle and that’s the reason why it does not work. 


The Spring approach is certainly interesting and worth exploring. But I thought given that business central is a CDI environment, that was the correct way to do it..?
it certainly is, though you must follow CDI completely to make it work - meaning make all cdi beans available on application boot time via application class path

Maciej

Nenad Vukobratović

unread,
Jun 16, 2016, 9:01:25 AM6/16/16
to jBPM Usage, nvukob...@gmail.com, nenad.vuk...@gmail.com

Hey Maciej,

Let me recap to see if I understand.. our deployment strategy using the RESTful interface to deploy our kjars to business-central does not give us CDI activation because the CDI boot cycle has already passed by the time we deploy our kjars. We currently use the in-memory model of deployment, meaning that with every server boot, we need to redeploy our kjars. This can easily be changed, which we plan to do at some point, to a persistent kjar deployment. Would this change up things with the *next* server boot at our kjars would then be available at server boot time? Would they *then* be included in the CDI cycle?

If not, then if I understand what you are saying correctly, we need to have our handlers jar (perhaps the process one as well) on the classpath. This can mean the WEB-INF/lib folder of business central. I find this deployment approach unsustainable as it requires a 15 jar file drop into business-central/WEB-INF/lib. Another approach perhaps then, is to wrap everything up into a war file, have our dependencies and their needed libraries (spring etc.) in the war/WEB-INF/lib, which would then trigger a CDI cycle at deploy time. I wonder, if this is the path to follow, how do we register our processes and handlers then?

If I didn't get this right, and I'd say there is a fair chance it might be the case, what then, is the recommended approach to deploy process and handler kjars to business-central to get CDI activation? I mean in a bit more specific steps that make all cdi beans available at application boot time via classpath :-)..

Thanks,
Nenad

Maciej Swiderski

unread,
Jun 16, 2016, 9:49:37 AM6/16/16
to Nenad Vukobratović, jBPM Usage, nenad.vuk...@gmail.com
Nenad,
On 16.06.2016, at 15:01, Nenad Vukobratović <nvukob...@gmail.com> wrote:


Hey Maciej,

Let me recap to see if I understand.. our deployment strategy using the RESTful interface to deploy our kjars to business-central does not give us CDI activation because the CDI boot cycle has already passed by the time we deploy our kjars.
correct, the deployment of kjars is after application started and thus cdi conatiner is done with booting as well

We currently use the in-memory model of deployment, meaning that with every server boot, we need to redeploy our kjars. This can easily be changed, which we plan to do at some point, to a persistent kjar deployment. Would this change up things with the *next* server boot at our kjars would then be available at server boot time? Would they *then* be included in the CDI cycle?
no, it still deploys kjar after application started as it’s not part of application life cycle - in terms of JEE application


If not, then if I understand what you are saying correctly, we need to have our handlers jar (perhaps the process one as well) on the classpath. This can mean the WEB-INF/lib folder of business central. I find this deployment approach unsustainable as it requires a 15 jar file drop into business-central/WEB-INF/lib.
depending on how many other deployment units you will have there it might be considered deployment of entire workbench war with included additional jars. 

Another approach perhaps then, is to wrap everything up into a war file, have our dependencies and their needed libraries (spring etc.) in the war/WEB-INF/lib, which would then trigger a CDI cycle at deploy time. I wonder, if this is the path to follow, how do we register our processes and handlers then?
that would mean building complete custom app with kie apis. You can look at extening kie server instead with required capabilities. you can find some details here


If I didn't get this right, and I'd say there is a fair chance it might be the case, what then, is the recommended approach to deploy process and handler kjars to business-central to get CDI activation? I mean in a bit more specific steps that make all cdi beans available at application boot time via classpath :-)..
in general you cannot bind cdi beans that are added to kjar dependencies to be visible to cdi container. 
Reply all
Reply to author
Forward
0 new messages