5 Replies Latest reply on Jan 5, 2007 4:57 AM by Michael Singer

    Injection / Outjection

    Michael Singer Newbie

      I still have troubles to understand how this bijection stuff works. What I want to achieve is the following:

      I have a SFSB called TestSessionBean:

      @Scope(ScopeType.SESSION)
      @Clustered
      @Name("testSessionBean")
      @Stateful
      public class TestSessionBean implements TestSession, Serializable {
      
       @Logger
       private Log log;
      
       private Session someSession;
      
       private TabItem activeTab;
      
       public TabItem getActiveTab() {
       return activeTab;
       }
      
       public void setActiveTab(TabItem activeTab) {
       this.activeTab = activeTab;
       }
      
       public Session getSomeSession() {
       this.initSomeSession();
       return this.someSession;
       }
      
       private void initSomeSession() {
       ...
       }
      
       @PrePassivate
       @Destroy
       @Remove
       public void passivate() {
       if (this.someSession != null) {
       this.someSession.logout();
       }
       }
      
       @PostActivate
       public void activate() {
       this.initSomeSession();
       }
      
       public String getHello(){
       return "Hello";
       }
      
      }
      


      I want to inject this TestSessionBean into another SFSB called TabBean:

      @Stateful
      @Scope(ScopeType.SESSION)
      @Name("foo.bar.TabBean")
      @Clustered
      public class TabBean implements Tab, Serializable {
      
       @In
       public TestSession testSessionBean;
      
       private TabItem activeTab;
      
       private Collection<TabItem> tabs = new Vector<TabItem>();
      
       public Collection getTabs() {
       return tabs;
       }
      
       public TabItem getActiveTab() {
       return activeTab;
       }
      
       public void setActiveTab(TabItem activeTab) {
       this.activeTab = activeTab;
       testSessionBean.setActiveTab(activeTab);
       }
      
       public void setInit(String[] tabArray) {
       for (int i = 0; i < tabArray.length; i++) {
       tabs.add(createTabItem(tabArray.split(";")));
       }
       if (tabs.size() > 0) {
       activeTab = tabs.iterator().next();
       }
      
       }
      
       private TabItem createTabItem(String[] vals) {
       if (vals.length != 4) {
       System.out.println("Wrong tab values inserted!");
       }
       return new TabItemImpl(vals[0], vals[1], vals[2], vals[3], this);
       }
      
       @Destroy
       @Remove
       public void destroy() {
       }
       }
      


      The TabBean gets configured with components.xml:

      <components>
       <component name="org.jboss.seam.core.resourceBundle">
       <property name = "bundleNames">
       <value>bundle</value>
       </property>
       </component>
      
       <component name="org.jboss.seam.core.init">
       <property name="debug">true</property>
       <property name="jndiPattern">join2learn/#{ejbName}/local</property>
       </component>
      
       <component name="org.jboss.seam.core.manager">
       <!-- half second wait for conversation lock on concurrent requests -->
       <property name="concurrentRequestTimeout">500</property>
       <!-- 120 second conversation timeout -->
       <property name="conversationTimeout">120000</property>
       <property name="conversationIdParameter">cid</property>
       <property name="conversationIsLongRunningParameter">
       clr
       </property>
       </component>
      
       <component class="org.jboss.seam.core.Ejb"
       installed="false" />
      
       <component class="foo.bar.TabBean"
       name="tabBean">
       <property name="init">
       <value>0;tab.startpage;tab1;startpage</value>
       </property>
       </component>
      </components>
      


      My ejb-jar.xml is the seam default one.

      My problem is, that I get a NPE in TabBean if I try to invoke a method on the injected TestSessionBean and if I debug this stuff the testSessionBean variable is in fact null.

      The TestSessionBean is first accessed in my index.xhtml page with the following call:

      <h:outputLabel value="#{testSessionBean.hello}" />
      


      After that call I go to the debug.seam page and both the testSessionBean and the tabBean show up in the Session Context.

      When I then click the link on the index page which invokes tabBean.setActiveTab(...) I get the NPE.

      I also already tried all combinations of the @In Parameters which also didn't work out.

      If I remove the @In and initialize testSessionBean with

      TestSession testSessionBean = (TestSession)Component.getInstance("testSessionBean");
      


      everything works but I suppose its not the same as with the @In annotation...

      I then added this to the TabBean:

      @In(create=true)
      private FacesMessages facesMessages;
      


      and also this is not injected (which should work because FacesMessages is a seam standard component, isn't it?)

      I am really stuck on this one, maybe someone can point me in the right direction...


        • 1. Re: Injection / Outjection
          Norman Richards Master

          Try adding create=true:

          @In(create=true)
          public TestSession testSessionBean;
          


          • 2. Re: Injection / Outjection
            Norman Richards Master

            Sorry - I hit submit too soon.

            Please try that and post the debug log if it doesn't work.

            • 3. Re: Injection / Outjection
              Norman Richards Master

              One more note - you don't need the
              @Name("foo.bar.TabBean") annotation since you aren't ever using TabBean by that name.

              • 4. Re: Injection / Outjection
                Michael Singer Newbie

                Thank you for your reply.

                I tracked that all down to bad design. Sorry for this one...

                • 5. Re: Injection / Outjection
                  Michael Singer Newbie

                  I want to point out what problem I had to clarify this issue for others.

                  For the navigation component in my webapp i had a SFSB TabBean. This bean contained a Vector with TabItem objects.
                  In my jsf code I called the TabBean to return all TabItems like that:

                  <c:forEach var="tab" items="#{tabBean.tabs}">
                  


                  and for each tab I generated a

                  <h:commandLink value="#{messages[tab.name]}" action="#{tab.getNavigationAction}" />
                  


                  When my application is running and I click on such a commandLink, tab.getNavigationAction is called on the according TabItem object.

                  This method did two things. It returns the navigation string where to go to. Now the problematic thing.

                  Each TabItem stores a reference to the TabBean. If TabItem.getNavigationAction is called then this method calls tabBean.setActiveTab(this). setActiveTab then calls sessionBean.setActiveTab(...) where sessionBean is set via @In(create=true) in TabBean. In my case sessionBean was always null. This is because the Bijection mechanism seems to only work if a beans method is called from jsf and in my case the beans method was called from another bean.

                  Call to bean method from jsf:
                  The BijectionInterceptor first injects the object, then calls the bean method, then outjects if necessary and after that disinjects the injected object (sets it to null).

                  Call to bean method from another bean (which is called from jsf):
                  The BijectionInterceptor injects the object correctly, then invocation.proceed() has no effect since the invocation is not from jsf, then outjection should occur, after that the object is disinjected. And after that the beans method is invoked (and the injected object is null because is already disinjected...)

                  pfuhh...

                  I hope you understand my findings...