2

I am coding a Java EE application that provides REST services via JAX-RS resource classes, the application makes extensive use of CDI. My resource classes are @RequestScoped, the application returns HTTP Status 202 Accepted to the caller and executes the work asynchronously.

I would like to return a "process ID" so the caller can periodically request the overall status of the long running "process" that I am executing on their behalf.

While processing these requests my application also interacts asynchronously with other systems via REST by supplying a "callback URL" that these remote servers POST back (along with results and status) to my application when the assigned task is complete.

I am looking for a way for all the beans involved in the execution of a "process" to share a common status for that "process id". My initial thought was to inject a status bean with a new @ProcessScoped CDI scope to form a common bean pool for any given process.

The crux of my problem is where to store these beans and how to group them? It seems like a chicken and egg situation because CDI is going to need to know the process id for any given bean in order to pool them together.

I have read articles on how CDI does this for it's standard scopes; and I have looked at sample code for creating custom CDI scopes. For example, @SessionContext uses the HttpSession from the Servlet specification to store the bean instances. Because our "process" is somewhat arbitrary, I am struggling to come up with something that is common that I can use to index or store these beans.

Ideally the @ProcessScope would work transparently to the application code, i.e. the process id can be queried but is created and maintained by the CDI extension alone.

Thanks for any help or advice or inspiration you can offer.

6
  • Please correct me if I missed something but isn't your ProcessScope very similar to a ConversationScope which already exists? If so you could either use that or at least get some ideas of how it is implemented. When implementing it yourself you'd need a ProcessContext anyways so if you are able to detect when a process is being started and when it is finished you'd store the related beans in that context.
    – Thomas
    Commented Dec 19, 2016 at 16:24
  • Hi Thomas ConversationScoped apears to be JSF centric, there is no conversation with the end user during a REST interaction. I did just come across a similar question on StackOverflow (stackoverflow.com/questions/38395462/…) which I am looking at now. Given that this question is so similar I would to understand why it was closed as "off topic" by @Bohemian
    – mikee
    Commented Dec 19, 2016 at 16:54
  • I don't see that question being closed so I'm not sure what you mean here. Besides that processes and conversations are very similar. It's true that ConversationScoped originates from JSF but it isn't limited to it (we've been using conversations and similar scopes with struts2 etc.). But think about it: what is a process? It's some finite unit of work that is started by someone or something and which one or more processes/services/systems are involved in. Now replace one of those "systems" by the user and you basically get a conversation. Thus the concepts are very similar.
    – Thomas
    Commented Dec 19, 2016 at 17:06
  • I am not sure how the conversation id would be communicated between all the contributors to the process, or how CDI would understand how to interpret it? I am starting to think my assumption that CDI was the answer to this problem is flawed, and perhaps I would be better of looking at an events and observers pattern instead to allow the contributors to communicate status between each other?
    – mikee
    Commented Dec 19, 2016 at 17:34
  • Hmm, conversations themselves might not be the perfect match for your processes but they are similar which is why I suggested having a look at them. Of course you'd have to communicate the process id to all contributors but that should be doable as long as there is a means to identify those contributors (e.g. by them being called). Maybe you could provide a small example (ideally with a small diagram) that shows how your processes would work in general.
    – Thomas
    Commented Dec 20, 2016 at 9:14

1 Answer 1

1

None of the built in scope can work in this case, and a custom scope is the best way to go. Conversation scope will fail cause the conversation scope is maintained in an http session, and hence outside an http-request, it becomes impossible to get hold of the http-session. What you are trying to do is somewhat near a the new jsf flow-scope (for jsf).

With custom scope, you control the life time of these beans, and hence you have the leeway to store beans anywhere you want, even in a custom map(even serialized to db if they have state). You will have to initialize new bean for every process id, so that a lookup of a bean gives the process id, or a single process id can retrieve from the map, a set of matching beans.

You can define an Instance injection which can result to something to this effect:

@Inject
@Any
Instance<MyBean> processingBeans;

//Somewhere in status call method
Instance<MyBean> processIdBeans = processingBeans.select(SomeQualifierForProcessId(processId));
processIdBeans.forEach((bean) -> bean.getState());

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.