6 Replies Latest reply on Jan 27, 2010 8:38 AM by Nicklas Karlsson

    Inject private Conversation conversation always null

    Jason Porter Master

      I'm not sure if this is a bug, or if I'm doing something I shouldn't be doing :)  The code is below, but what's happening is the conversation is started via an Observer in one bean, then the conversation is used by a different observer (same event) on a different bean.  The second bean is @ConversationScoped, the first is @ApplicationScoped.  The conversation scoped bean never has a conversation that's non-null injected into it, very, very odd.


      <?xml version='1.0' encoding='UTF-8' ?>
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml"
            xmlns:ui="http://java.sun.com/jsf/facelets"
            xmlns:h="http://java.sun.com/jsf/html"
            xmlns:f="http://java.sun.com/jsf/core">
          <ui:composition template="/template.xhtml">
      
              <ui:define name="title">Simple Greeting</ui:define>
              <ui:define name="head">Simple Greeting</ui:define>
              <ui:define name="content">
                  <h:form id="greetme">
                      <p><h:outputLabel value="Enter your name: " for="name"/>
                          <h:inputText id="name" value="#{printer.name}"/></p>
                      <p><h:commandButton value="Say Hello" action="#{printer.createSalutation}"><f:ajax render="@form" execute="@form" /></h:commandButton></p>
                      <p><h:outputText value="printer.salutation = #{printer.salutation}"/> </p>
                      <p><h:outputText value="printer.old_salutation = #{printer.old_salutation}"/> </p>
                      <p><h:outputText value="myConversationStatus.conversationSattus = #{myConversationStatus.conversationSattus}"/> </p>
                      <p><h:outputText value="my_application_scope_bean.my_application_scope_counter = #{my_application_scope_bean.my_application_scope_counter}"/> </p>
                      <p><h:outputText value="my_conversation_scope_bean.my_conversation_scope_counter = #{my_conversation_scope_bean.my_conversation_scope_counter}"/> </p>
                      <p><h:outputText value="Prime number #{printer.primeNumber} is hit!" rendered="#{printer.primeNumber != 0}"/></p>
                  </h:form>
              </ui:define>
      
          </ui:composition>
      </html>



      The call to the Say Hello button starts things off.


      @Named
      @ConversationScoped
      public class Printer implements Serializable
      {
      
          @Inject @Informal
          GreetingInterface greeting;
          @Inject
          Conversation conversation;
          @Inject
          MyConversationStatus cstatus;
      
          @Inject Event<SalutationEvent> createSalutationEvent;
      
          private String name;
          private String salutation = "nothing yet!";
          private String old_salutation = "nothing yet!";
          private int primeNumber;
      
          public void startConversation()
          {
              cstatus.setConversationSattus("on");       
          }
      
          public void endConversation()
          {
              cstatus.setConversationSattus("off");
              conversation.end();
          }
      
          public void createSalutation()
          {
              this.primeNumber = 0;
              this.createSalutationEvent.fire(new SalutationEvent());
              
              this.old_salutation = salutation;
              this.salutation = greeting.greet(name);
          }
      
          public String getSalutation()
          {
              return salutation;
          }
      
          public void setName(String name)
          {
              this.name = name;
          }
      
          public String getName()
          {
              return name;
          }
      
          /**
           * @return the old_salutation
           */
          public String getOld_salutation()
          {
              return old_salutation;
          }
      
          /**
           * @param old_salutation the old_salutation to set
           */
          public void setOld_salutation(String old_salutation)
          {
              this.old_salutation = old_salutation;
          }
      
          public void primeEventObserver(@Observes @Prime Integer pPrimeNumber)
          {
              this.primeNumber = pPrimeNumber;
          }
      
          public int getPrimeNumber()
          {
              return this.primeNumber;
          }
      }



      In this class the conversation is never null, I can start up the conversation just fine, there aren't any issues.


      @ApplicationScoped
      @Named("my_application_scope_bean")
      public class MyApplicationScopeBean
      {
      
          private int my_application_scope_counter;
          @Inject
          Conversation conversation;
          @Inject @Prime
          Event<Integer> primeEvent;
          @Inject
          MyConversationStatus convStatus;
      
          public int getMy_application_scope_counter()
          {
              return this.my_application_scope_counter;
          }
      
          public void setMy_application_scope_counter(int pMy_application_scope_counter)
          {
              this.my_application_scope_counter = pMy_application_scope_counter;
          }
      
          private void salutationObserver(@Observes SalutationEvent event)
          {
              this.addToCounter();
          }
      
          public void addToCounter()
          {
              this.my_application_scope_counter++;
              if (this.my_application_scope_counter % 5 == 0)
              {
                  this.conversation.begin();
                  this.convStatus.setConversationSattus("on");
              }
      
              if (this.my_application_scope_counter > 5 && (this.my_application_scope_counter - 4) % 5 == 0)
              {
                  this.conversation.end();
                  this.convStatus.setConversationSattus("off");
              }
      
              if (this.my_application_scope_counter < 20 && this.isPrime(this.my_application_scope_counter))
              {
                  primeEvent.fire(this.my_application_scope_counter);
              }
          }
      
          private boolean isPrime(int pNumToCheck)
          {
              switch (pNumToCheck)
              {
                  case 1:
                  case 2:
                  case 3:
                  case 5:
                  case 7:
                  case 11:
                  case 13:
                  case 17:
                      return true;
                  default:
                      return false;
              }
          }
      }



      When the observer is invoked here, the class property conversation is always null.  It's even null in the constructor.  I must say I'm more than baffled at this one.


      @Named("my_conversation_scope_bean")
      @ConversationScoped
      public class MyConversationScopeBean implements Serializable {
          private static final long serialVersionUID = 2346533234L;
          
          private int my_conversation_scope_counter;
      
          @Inject private Conversation conversation;
      
          @Inject public MyConversationScopeBean()
          {
              this.my_conversation_scope_counter = 0;
          }
      
          public int getMy_conversation_scope_counter()
          {
              return this.my_conversation_scope_counter;
          }
      
          public void addToCounter()
          {
              this.my_conversation_scope_counter++;
          }
      
          // Had to have CDI inject the conversation into the observer because the field on the class was always null,
          // very strange, talking to the Weld devs about it.
          private void salutationObserver(@Observes(notifyObserver=Reception.IF_EXISTS) SalutationEvent event, Conversation pConversation)
          {
              if (!pConversation.isTransient())
              {
                  this.addToCounter();
              }
          }
      }



      Any thoughts or ideas from anyone?