0

I'm using the following code to test the operation of ConversationScoped, but I don't understand how it works. I open conversation, set the value of conversationBean.i = 1, then close conversation and open a new conversation, but the value of conversationBean.i is still 1, why? it was supposed to be null, wasn't it?

@WebServlet(value = "/tes")
public class MyTag extends HttpServlet {
    @Inject
    ConversationBean conversationBean;
    @Override
    protected void doGet(HttpServletRequest req,
                         HttpServletResponse resp) {
        conversationBean.startConversation();
        conversationBean.doSomething();
        conversationBean.out();
        conversationBean.endConversation();
        conversationBean.startConversation();
        conversationBean.out();
    }
}

@ConversationScoped
class ConversationBean implements Serializable {
    int i = 0;
    @Inject
    private Conversation conversation;
    public void startConversation() {
        conversation.begin();
    }
    public void doSomething() {
        i++;
    }
    public void out() {
        System.out.println(i);
    }
    public void endConversation() {
        conversation.end();
    }
}

Tell me, maybe I got it wrong? If so, could you provide an easy example where it really shows that when closing a conversation, all the resources associated with it are cleared?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555

1 Answers1

0

@ConversationScoped is primarily about JSF, in which context the word "conversation" has a particular meaning. I haven't really used it, but I expect that it would sometimes make sense for the backing bean of a JSF component.

Conversation objects provide a way to access certain properties of JSF conversations.

I open conversation, set the value of conversationBean.i = 1, then close conversation and open a new conversation, but the value of conversationBean.i is still 1, why?

The injected ConversationBean instance may change from request to request, but the one observed by a given invocation of one of your servlet's request-handling methods will not change during the execution of that method. Naturally, then, if you modify that bean's state during doGet() then you can observe that modification later in doGet().

Moreover, Conversation.startConversation() and Conversation.endConversation() don't do what their names might lead you to think they do. They control whether the current conversation is "long-lived" or "transient", which affects its lifecycle, but they don't actually start or end a conversation. The names make a little more sense if you think in terms of starting and ending long-lived conversations specifically, but even then they're not really right. A single setLongLived(boolean) method would be more intuitive.

it was supposed to be null, wasn't it?

No.

Tell me, maybe I got it wrong?

You have incorrect expectations.

And although it's valid, it doesn't usually make sense to switch the current conversation back and forth between transient and long-lived multiple times while servicing the same request. Request boundaries are inside conversation boundaries, so only the conversation type prevailing at the end of request processing matters.

If so, could you provide an easy example where it really shows that when closing a conversation, all the resources associated with it are cleared?

That does not happen per se. If you have a @ConversationScoped bean then you can expect to get different instances in different conversation contexts, but Conversation.startConversation() and Conversation.endConversation() don't get you a different conversation context for the current request. And if you hold on to a reference to a conversation-scoped bean past the end of the lifetime of the conversation context from which you obtained it, you should not expect that to cause its properties to be modified.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157