CDI Conversation Bean - BusyConversationException
Asked Answered
U

1

6

I have a Conversation scoped bean, ComponenteM, that is injected in a Request Scoped bean, ComponenteC.

@Named
@RequestScoped
public class ComponenteC implements Serializable {
    @Inject
    ComponenteM componenteM;
}


ComponenteC has an export method that is invoked by an HtmlCommandLink (created programmatically). The export method calls a webservice that integrates with SAP BO webservice in order to export a report to excel. However, only when the call takes too long, I get a BusyConversationException. Every other export that is takes less that 10 minutes is successful.
I have no other call in the conversation meanwhile (AJAX or non-AJAX calls). I've tried setting an explicit timout to the conversation bean when beginning the conversation but I read that it only works as a suggestion to the CDI container and it may be ignored:

public void beginConversation() {
    if (conversation.isTransient()) {
        conversation.setTimeout(60 * 60 * 1000);
        conversation.begin();
    }
}


The error is:
Root cause of ServletException.org.jboss.weld.context.BusyConversationException: WELD-000322 Conversation lock timed out: 1

I've also tried making the export request via thread and then returning the exported document to the conversation. My idea was to have one thread busy handling the exportation of the document and componenteC, while waiting for the thread to complete, would check occasionally do componenteM.beginConversation();


I'm trying to understand why a BusyConversationException is thrown even if there are no concurrent requests.
Thank you.

Urgent answered 11/8, 2015 at 10:40 Comment(5)
Why dont you use a service that does an asynchronous request? If you are in ejb-container, you could convert the conversationscoped bean into a stateless bean and annotate the method as asynchronous, if not, you can still use ExecutorService to fire up an asynchronous request, so that your component does not have to wait for the resultTeratology
I'm not using ExecutorService but I am creating a thread pool. I need my component to wait for the result because I need the to know when the thread is done writing the exported report to a folder so that I can retrieve it to the component.Urgent
Creating your own thread pool in java webcontext - you better check on how the executor service works, and use the one that returns a futureTeratology
How is the executor service any better? The context is still not active in the threads and the conversation would still have to wait for the thread to be over so it returns the exported document. I don't mind letting the conversation wait for the thread as long as the error BusyConversationException isn't thrown when the export process takes too long. At first I didn't have threads at all, I've created threads in order to avoid the conversation being idle too long (that's why the conversation, while is waiting for the thread, is verifying its own status).Urgent
Should've posted the full stacktrace and the access log.Seism
A
0

I recently faced this same issue in an application. The asynchronous loading of elements was working fine, except for the one page with @ConversationScoped.

My solution was to simply make the requests synchronous for this one page. On this page, the elements are loaded asynchronously with PrimeFaces "deferred" parameter, like this:

<p:outputPanel id="asyncMenu" deferred="true">...</p:outputPanel>

When I set the parameter to "false" everything worked as expected. @ConversationScoped introduces an URL parameter "cid", so I simply set deferred to "false" only when on a site with cid:

<p:outputPanel id="asyncMenu" deferred="#{empty param.cid ? true : false}">...</p:outputPanel>

While it feels a little hacky, it works perfectly fine in my case and will also work in the future if we decide to add a new page relying on @ConversationScoped.

Accusation answered 26/6, 2019 at 8:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.