Hi folks,

I've been using Orchestra for a few months now and in doing so I've been questioning some major implementation decisions, to be more specific I really want to discuss if it's really necessary to bind beans to a certain conversation (and therefore also a certein persistence context!). Let me give you some examples:


Example 1)
I've developed some views for a search dialog that I wanted to use in at least two different conversations. Everything worked fine for the first conversation. The following code listing should give you an idea of the problem.

///

view.xhtml
 <h:inputText value="#{conversationBean.value}" />

spring-bean-config.xml
 <bean id="conversationBean" class="..." scope="conversation.manual"
   orchestra:conversationName="conversationA" />

\\\

Maybe some of you have realized my problem by now: The bean somehow depends on the conversation and as the view depends on the bean I can't use it with a different conversation (or at least I'm missing a major feature of Orchestra). :-f

I've solved this issue by creating some Facelets components so that I'm able to pass the conversation bean as parameter. However, I had to duplicate navigation rules, etc, i.e. now I've got the following structure:

///

viewA.xhtml
 <my:view bean="#{conversationABean}" />

viewB.xhtml
 <my:view bean="#{conversationBBean}" />

view.xhtml
 <h:inputText value="#{bean.value}" />

spring-bean-config.xml
 <bean id="conversationABean" class="..." scope="conversation.manual"
   orchestra:conversationName="conversationA" />

 <bean id="conversationBBean" class="..." scope="conversation.manual"
   orchestra:conversationName="conversationB" />

\\\


Example 2)
In a different part of the same application I've created a view that should serve for three different usecases. Basically the view doesn't change for these usecases at all, but the logic of the backing bean does. My first approach was to determine the specific page bean at runtime in the action method that navigates to this view. This action method was supposed to register the specific page bean under a common name. So somehow it can be said that I wanted to use "polymorphic beans".

///

public String action() {
  Conversation conversation = getCurrentConversation();

  switch (criterium) {
    case CASE_A:
      conversation.setAttribute("commonBean", specificBeanA);
      break;

    case CASE_B:
      conversation.setAttribute("commonBean", specificBeanB);
      break;

    case CASE_C:
      conversation.setAttribute("commonBean", specificBeanC);
      break;

    default:
      throw new IllegalStateException(); // shouldn't occur anway
  }

  return outcome;
}

view.xhtml
 <h:commandButton action="#{commonBean.save}" />

\\\

However, that wouldn't work for two reasons:
- Orchestra only knows how to resolve Spring beans as the bean definition determines the conversation being used (well, Orchestra doesn't know how to resolve anything, actually it's the EL-/VariableResolver of Spring that does this job in this case). It's only possible to resolve such variables if the view knows which conversation it should access (i.e. if one would develop a custom ELResolver that knows how to resolve expressions like #{conversation.conversationA.commonBean} - *cough* problem of the first example *cough*). - Orchestra wouldn't create a persistence context for that bean as the persistence interceptor only gets attached to Spring beans. (No, I'm not telling you to modify the setAttribute method so that advices will be attached. I'm rather telling you to use conversation listeners instead for persistence support, just like Web Flow does).

I was able to work around this issue by introducing an additional indirection, i.e. I'm resolving that bean with the expression #{pageAccessor['commonBean']}, but that's just not intuitional.



However, please don't get me wrong. I don't want to hear anything about certain workarounds that I could have used in these cases as I think that these usecases aren't exceptional enough to justify workarounds. Of course, the current approach has got its advantages too (e.g. switching arbitrarily between different conversations as there is no hierarchical structure), but at least I haven't needed this feature yet.

Summarizing it can be stated that I'd propose you to rewrite conversation handling for the next major release and I'd be willing to contribute. Note that I don't want to drop support for these "named conversations", but I think that this usecase is not the default one for conversations.

regards,
Bernhard Huemer

Reply via email to