8 Replies Latest reply on Nov 7, 2012 4:29 PM by tony.herstell1

    Stateful bean and dependent lacking conversation.

    tony.herstell1

      I have a Stateful Converstional bean and it had some stateful code that was now common to other beans so needed to be extracted.

       

      I extracted this stateful code into a new bean and I was trying to inject it back into this original bean. My Thinking was that it would be set up with the same scope of the parent bean as it was a "dependent" bean... hence it would also become Conversational so I Injected Conversation.

       

      This new Dependent Stateful injected bean needed to have the conversation not null but the conversation is null as I have not called my "init" method which will starts the conversation on the parent bean.

       

      How do I achieve this?

        • 1. Re: Stateful bean and dependent lacking conversation.
          tony.herstell1

          Parent bean...

           

          //Tell prettyfaces to use this bean when the pattern matches and show the xxx page. Also support a Query Param (cid).

          @URLMappings(mappings = { @URLMapping(id = "selectXXXXForVisualisation", pattern = "/xxx/xxxToyyy", viewId = "/pages/xxx/visualisation/xxxToyyy.xhtml")})

          // Leverage EJB to get Transactional Support

          @Stateful

          // Lets be long running (multiple client-server round trips) - Needs Extended on

          // PersistanceContext too to hold onto my objects and not get LIEs.

          @ConversationScoped

          // EL Can can find me...

          @Named

          public class xxxVisualisationController extends BaseController {

             private Logger logger = Logger.getLogger(xxxVisualisationController.class.getName());

             @SuppressWarnings("unused")

             @URLQueryParameter("cid")

             private String cid;

             // DON'T let any Entities be Proxied by WELD so just use class local.

             // According to this definition, JPA entities are technically managed beans.

             // However, entities have

             // their own special lifecycle, state and identity model and are usually

             // instantiated by JPA or using

             // new. Therefore we don't recommend directly injecting an entity class. We

             // especially recommend

             // against assigning a scope other than @Dependent to an entity class, since

             // JPA is not able to

             // persist injected CDI proxies.

             private List<xxx> xxxs;

           

           

          ...

           

          // A good place to START a conversation from. ** land here off a menu

              // click...

              public String init() {

                  this.logger.info(">>>init");

                  if (!this.conversation.isTransient()) {

                      this.logger.info("Existing conversation found:" + this.conversation.getId() + " Ending it...");

                      this.conversation.end();

                  }

                  this.logger.info("+++CONVERSATION START");

                  this.conversation.begin(); // START THE LONG RUNNING CONVERSATION

                  this.logger.info("conversation:" + this.conversation.getId());

                  this.xxxxs = getXxxs();                                                                                                        <<-- would call out to injected bean here...

                  this.buildMindMap();

                  this.logger.info("<<<init");

                  return "pretty:selectXXXForVisualisation";

              }


          • 2. Re: Stateful bean and dependent lacking conversation.
            tony.herstell1

            Is this more indicative of JEE 6 (Weld) not supporting Conversations properly? or just my stupidity?

            I am supprised that I have not found an answer to this problem yet.

            • 3. Re: Stateful bean and dependent lacking conversation.
              mkouba

              Hi,

              I'm not completely sure I understand your use case. It would be helpful if you provide some simplified test case (e.g. Arquillian-based test).

              • 4. Re: Stateful bean and dependent lacking conversation.
                tony.herstell1

                Sorry but Arquillian does not support the J6EE spec as it does not support Conversations so there is no way to produce an Arquillian test.

                 

                This is sad as this issue still remains unresolved.

                 

                This is the Use Case:

                A conversation bean injects another conversational (Dependent) class and the Conversation object in that class is null; when by this stage a conversation is active in the parent class.

                 

                As I am using EJB (Stateful) beans then I am not even sure this is the right place to ask the question as they are not CDI beans...

                 

                I hope that distinction between EJB and CDI dissapears at some point as it just adds confusion.

                 

                Now that EE is mostly fixed; I use the EJB beans as they seem perfectly acceptable inside a EE container and still provide transactions, security etc. which is why you want to use EJB beans in the first place.

                • 5. Re: Stateful bean and dependent lacking conversation.
                  luksa

                  Tony, take a look at https://github.com/luksa/weld-core/commit/3174ac6a99d0f06ea83ad77222e25af72f52e526

                   

                  Is this what you're talking about? BTW, this test passes.

                  • 6. Re: Stateful bean and dependent lacking conversation.
                    tony.herstell1

                    I will take a look at this.

                    I can see already you added the tag @Dependent to the dependent bean.


                    I just assumed that was the default so I didnt need it!

                     

                    I was adding:

                       @Stateful

                       @ConversationScoped

                    to my dependent bean as this, I assumed, would not be "configured by exception".

                     

                    I also see that you have a test, in Arquillian . Am I to conclude that Conversatin scope is now part of Arquillian out of the box as I am keen to use it (I have written test that are not conversational)?

                     

                    I assume that people in the trenches using Conversation Scope daily, for real world problems, will be keen to hear about this... was it announced as I know others keen to hear about it.

                     

                    Thanks

                    • 7. Re: Stateful bean and dependent lacking conversation.
                      luksa

                      Yes, you don't need to explicitly define the bean as @Dependent. The only reason I added the @Dependent annotation is so it would stand out that this is a dependent bean.

                       

                      Well, if you're adding @Stateful @ConversationScoped to the "dependent" bean, then it's really not a dependent bean.

                       

                      The Conversation bean will always be injected if you request it. Of course, the conversation is transient until you mark it as long-running with .begin().

                       

                      If I understood your problem, your injected Conversation was null? This shouldn't happen, unless you're instantiating the bean yourself (in this case, injection will not be performed, of course).

                      • 8. Re: Stateful bean and dependent lacking conversation.
                        tony.herstell1

                        I will re-code it all tonight...

                        The injected dependent bean was called after the main bean was well into its conversation.

                        I only enter my controllers through a "init" method (KISS).

                        e.g.:

                            public String init(String visualisationMode) {

                                this.logger.info(">>>init");

                                if (!this.conversation.isTransient()) {

                                    this.logger.info("Existing conversation found:" + this.conversation.getId() + " Ending it...");

                                    this.conversation.end();

                                }

                                this.logger.info("+++CONVERSATION START");

                                this.conversation.begin(); // START THE LONG RUNNING CONVERSATION

                                this.logger.info("conversation:" + this.conversation.getId());

                                this.xxxxxx = getXXxxxxx(); <--- this was extracted into a dependent bean; so the conversation should have been started (see this.conversation.begin above).

                                this.setupXxxxValues();   <--- this was extracted into a dependent bean; so the conversation should have been started (see this.conversation.begin above).

                                this.buildMindMap();

                                this.logger.info("<<<init");

                                return "pretty:xxxxToyyyyVisualisation";

                            }