Inject private Conversation conversation always null
lightguard Jan 18, 2010 9:42 AMI'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?