1 2 Previous Next 15 Replies Latest reply on Jun 26, 2008 9:06 AM by dhinojosa

    Outjection not working at all

    imcmahon

      I have set up a simple application that's deployed and working in Glassfish.  I have a working facelet page with a command button that calls a SFSB method which populates data in my database via an injected entity manager, and that's all working just fine.  However, I'm trying to retrieve data from the database and outject it back to my view and I can't make it work at all.


      I was initially basing it off the message example, using a @DataModel list and a @Factory to populate it.  The @Factory call happens on every page load and successfully populates the list in the SFSB, but the view never sees anything but null.


      I've since simplified it quite a bit and I'm just trying to set a String annotated with @Out and be able to display it in the view, but it's still always null.



      @Stateful
      @Name("TestManager")
      @Scope(ScopeType.SESSION)
      public class TestManagerBean implements Serializable, TestManagerLocal {
          @PersistenceContext(unitName="av8")
          private EntityManager em;
      
          @Out(scope=ScopeType.CONVERSATION)
          private String hello = "Hello!";
      
          @Factory("hello")
          public void initHello() {
              hello = "Hello there!";
          }
      
          @Remove public void destroy() {}
      }



      @Local
      public interface TestManagerLocal {
      
          public void initHello();
      
          public void destroy();
      }



              <ui:define name="content">
                  <h1>Management</h1>
      
                  <f:view>
                      <h:form>
                          <h:outputText value="#{hello}"/>
                      </h:form>
                  </f:view>
      
              </ui:define>




      I've tried everything I can think of to make this work, and no luck.  I've searched both here and the jboss forums for similar issues, and I haven't been able to find anything even close.

        • 1. Re: Outjection not working at all
          dhinojosa

          Where did you declare a hello component?


          If you have not done so, add the following to your components.xml


              <component name="hello" class="java.lang.String" scope="CONVERSATION"/>
          



          it should work after that.

          • 2. Re: Outjection not working at all
            dhinojosa

            Ooops didn't see that your bean was a session.  Put whatever scope you require in your mapping.


            ;)

            • 3. Re: Outjection not working at all
              imcmahon

              I'm not following you...


              I stuck that Scope CONVERSATION on the @Out on hello just to try to get it to work... I don't need conversation scope for sure, but something I read somewhere led me to try that.  I meant to weed it back out of what I posted, but obviously forgot.



              If I can get any of the simplest form of outjection working, I'll be able to hopefully work forward from there, but so far even the simplest stuff stymies me.


              I know for sure that my view facelet is talking to the SFSB correctly, because I can call methods in the SFSB from an h:commandButton in the facelet.

              • 4. Re: Outjection not working at all
                dhinojosa

                That's what I was saying, you need to map a component 'hello' in components.xml  


                <component name="hello" class="java.lang.String" scope="SESSION"/>
                



                Here...
                I did another sample on my app just to make sure it works fine..


                in my components.xml


                    <component name="favoriteMusic" class="java.lang.String" auto-create="true" scope="CONVERSATION"/>
                



                in a factory bean


                package com.evolutionnext;
                
                import org.jboss.seam.annotations.Name;
                import org.jboss.seam.annotations.Scope;
                import org.jboss.seam.annotations.Factory;
                import org.jboss.seam.annotations.Out;
                import org.jboss.seam.ScopeType;
                
                /**
                 * Created by danno
                 * User: danno
                 * Date: Jun 24, 2008
                 * Time: 9:10:30 PM
                 * url: <a href="http://www.evolutionnext.com">http://www.evolutionnext.com</a>
                 * email: <a href="mailto:dhinojosa@evolutionnext.com">dhinojosa@evolutionnext.com</a>
                 */
                @Name("makeItRockAndRoll")
                @Scope(ScopeType.CONVERSATION)
                public class MakeItRockAndRoll {
                    @Out()
                    public String favoriteMusic;
                
                    @Factory("favoriteMusic")
                    public void doIt() {
                        this.favoriteMusic = "ROCK AND ROLL BABY!";
                    }
                }
                
                



                and somewhere in a webpage somewhere:


                <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                <ui:composition xmlns="http://www.w3.org/1999/xhtml"
                                xmlns:s="http://jboss.com/products/seam/taglib"
                                xmlns:ui="http://java.sun.com/jsf/facelets"
                                xmlns:f="http://java.sun.com/jsf/core"
                                xmlns:h="http://java.sun.com/jsf/html"
                                xmlns:t="http://myfaces.apache.org/tomahawk"
                                xmlns:rich="http://richfaces.org/rich"
                                template="layout/template.xhtml">
                
                    <ui:define name="main">
                       <h1>My favorite music, well that's #{favoriteMusic}</h1>
                    </ui:define>
                </ui:composition>
                



                and it all works. ;)

                • 5. Re: Outjection not working at all
                  imcmahon

                  Am I going to have to define everything like that in components.xml?



                  What I'm actually trying to do is display a list of entities out of the database using a @DataModel, following the Message example.   None of the examples I've looked at have had to explicitly define stuff in components.xml!

                  • 6. Re: Outjection not working at all
                    imcmahon

                    Ok, I tried your example, and it fails with an exception telling me that 'hello' is final.


                    Realistically, I need the SFSB to have something like:


                    @DataModel
                    private List<Thing> thingsList;
                    
                    @Factory("thingsList")
                    public void findThings() {
                      thingsList = em.createQuery("some query").getResultList();
                    }



                    and then the facelet would display it in a dataTable.



                    I had it written that way initially, and I was able to verify in a debugger that findThings() was running on the facelet load and successfully populating thingsList from the database.   Based on what you said above, does that mean that I'd have to define thingsList as a component in components.xml?  Seems somewhat counter to all the seam examples I've seen so far, but I haven't been able to do ANYTHING to make this stuff work.

                    • 7. Re: Outjection not working at all
                      dhinojosa

                      Update: Well, I tried it without mapping my string on components.xml and it worked. I guess if you are merely outjecting it is happy to do so, which actually counters what the docs say If the attribute is null, an exception is thrown.  But hey, I am happy it does so and still everything worked out great. So I stand corrected on that aspect. 


                      As per the @DataModel I never have to declare that Collection object in annotations or components.xml.


                      But all this is digression...


                      So back to your 'thingsList' example that you need working....


                      You verified that the bean is working so I have to ask what does your web page look like where your h:dataTable is located?




                      • 8. Re: Outjection not working at all
                        imcmahon

                        Site's been down all day... frustrating!



                        Ok, I have two different things I tried.  Here's the first:


                        @Stateful
                        @Name("aircraftManager")
                        @Scope(ScopeType.SESSION)
                        public class AircraftManagerBean implements Serializable, AircraftManagerLocal {
                            private static final long serialVersionUID = 1881413500711441951L;
                            
                            @PersistenceContext(unitName="av8", type= PersistenceContextType.EXTENDED)
                            private EntityManager em;
                        
                            @DataModel
                            private List<AircraftCategory> categories;
                        
                            @Factory("categories")
                            public void loadCategories() {
                                categories = em.createQuery("SELECT c FROM AircraftCategory c").getResultList();
                            }
                        
                            public String loadBaseInfo() {
                                AircraftCategory cat = new AircraftCategory();
                                cat.setName("Airplane");
                                em.persist(cat);
                                
                                // initialize some data, snipped
                        
                                return "aircraftManager.xhtml";
                            }
                        
                            @Remove public void destroy() {}
                        }




                        local interface as you'd expect


                        entity looks as such:


                        @Entity
                        @Name("aircraftCategory")
                        @Scope(ScopeType.EVENT)
                        public class AircraftCategory implements Serializable {
                            private static final long serialVersionUID = 1881413500711441951L;
                        
                            @Id
                            @GeneratedValue(generator="AircraftCategorySeq")
                            @SequenceGenerator(name="AircraftCategorySeq",sequenceName="AIRCRAFT_CATEGORY_SEQ", allocationSize=5)
                            private int id;
                            private String name;
                        
                            public AircraftCategory() {}
                            public AircraftCategory(String name) { this.name = name; }
                        
                            public int getId() {
                                return id;
                            }
                        
                            public void setId(int id) {
                                this.id = id;
                            }
                        
                            public String getName() {
                                return name;
                            }
                        
                            public void setName(String name) {
                                this.name = name;
                            }
                        }



                        and the view:


                        <?xml version="1.0" encoding="UTF-8"?>
                        <!DOCTYPE composition
                                PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                                "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                        <ui:composition xmlns="http://www.w3.org/1999/xhtml"
                                        xmlns:h="http://java.sun.com/jsf/html"
                                        xmlns:f="http://java.sun.com/jsf/core"
                                        xmlns:ui="http://java.sun.com/jsf/facelets"
                                        template="layout.xhtml">
                        
                                <ui:define name="title">Aircraft Management</ui:define>
                        
                                <ui:define name="content">
                                    <h1>Management</h1>
                        
                                    <f:view>
                                        <h:form>
                                            <h:dataTable var="cat" value="#{categories}">
                                                <h:column>
                                                    <f:facet name="header">Category</f:facet>
                                                    <h:outputText value="#{cat.name}"/>
                                                </h:column>
                                            </h:dataTable>
                                            <h:commandButton value="Load Base Data" action="#{aircraftManager.loadBaseInfo}"/>
                                        </h:form>
                                    </f:view>
                        
                                </ui:define>
                        
                        </ui:composition>




                        Now, when this is deployed, I can hit /aircraftManager.seam, I get the view, the dataTable is empty.  Database doesn't contain any rows.   If I hit the commandButton, loadBaseData in the SFSB runs and populates the database and the view reloads.  Still nothing in the dataTable.


                        If I set a breakpoint on loadCategories(), I can see it getting run in each JSF lifecycle, and it's successfully pulling categories from the database, and List categories is populated.  However, that's never making it back to the view.

                        • 9. Re: Outjection not working at all
                          imcmahon

                          For my next trick, I decided to cut the EJB tier out of the picture.  I have no clue if I'm doing this part right or not, because i don't have a solid example to look at.   I created a POJO in the web tier:


                          @Name("seam")
                          public class SeamBean {
                              @Factory(value="things", scope= ScopeType.PAGE)
                              public List<String> findThings() {
                                  List<String> things = new ArrayList<String>();
                                  things.add("One thing");
                                  things.add("Two thing");
                                  things.add("Red thing");
                                  things.add("Blue thing");
                                  return things;
                              }
                          }




                          <?xml version="1.0" encoding="UTF-8"?>
                          <!DOCTYPE composition
                                  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                                  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                          <ui:composition xmlns="http://www.w3.org/1999/xhtml"
                                          xmlns:h="http://java.sun.com/jsf/html"
                                          xmlns:f="http://java.sun.com/jsf/core"
                                          xmlns:ui="http://java.sun.com/jsf/facelets"
                                          template="layout.xhtml">
                          
                                  <ui:define name="title">Test</ui:define>
                          
                                  <ui:define name="content">
                                      <h1>Test</h1>
                          
                                      <f:view>
                                          <h:form>
                                              <h:dataTable var="thing" value="#{things}">
                                                  <h:column>
                                                      <f:facet name="header">Things</f:facet>
                                                      <h:outputText value="#{thing}"/>
                                                  </h:column>
                                              </h:dataTable>
                                          </h:form>
                                      </f:view>
                          
                                  </ui:define>
                          
                          </ui:composition>



                          Now, nowhere in there did I do anything to tell Seam that the SeamBean component exists other than annotating it with @Name, which is why I mentioned that I don't know if I'm doing it right.  This example definitely doesn't work, and I haven't even seen the findThings() method get called on page views via the debugger.


                          • 10. Re: Outjection not working at all
                            imcmahon

                            Ok, a little bit of a minor breakthrough....


                            On my second example, the JavaBean component, I told Seam about it in components.xml thusly:


                            <component name="seam" class="test.SeamBean" auto-create="true" scope="EVENT"/>



                            After that, the outjection works properly and my dataTable is being populated.



                            Does that help anyone troubleshoot my first example?   Seam knows how to talk to the EJB, because the method call works, but somehow the outjection doesn't.   Frustrating!

                            • 11. Re: Outjection not working at all
                              imcmahon

                              It's breaking down somewhere in transit.  I'm tracing it with the debugger:


                              Object result = factoryMethod.getComponent().callComponentMethod( factory, factoryMethod.getMethod() );


                              We get there, and factoryMethod = FactoryMethod(public void com.prototechnical.av8.logbook.session.AircraftManagerBean.findThings()), and
                              factory = com.prototechnical.av8.logbook.session.AircraftManagerLocal_6498190.


                              Then, into callComponentMethod, and we get to             return Reflections.invokeAndWrap(interfaceMethod, instance);


                              I've traced it all the way through the invoke pipeline to Reflections.invoke(), where it calls method.invoke and runs through my SFSB factory method, and somewhere, somehow, somewhy, the result isn't getting back up the stack.   Everything in the pipeline does a return proceed() or return invoke() so I can't see who's dropping it.



                              I'm in over my head a bit here, but I really want this to work!

                              • 12. Re: Outjection not working at all
                                dhinojosa

                                Everything here that you are doing shouldn't be as hard as you are making it.


                                My suggestion, change every scope in your example to session just to make sure you will get what you need.  EVENT is too small of a scope, and it may be the reason for all your troubles.  Afterwards you can tune your scopes to work with what you need.


                                If you want to email me directly, I stay up pretty late. You can email me at dhinojosa@evolutionnext.com.


                                • 13. Re: Outjection not working at all
                                  dhinojosa

                                  Ok, gonna try this on my machine here.  It looks like everything is right.  The only thing I may be curious about is whether


                                  private List<AircraftCategory> categories;
                                  
                                  



                                  needs to have a setter exposed through the local interface.

                                  • 14. Re: Outjection not working at all
                                    dhinojosa

                                    Hey, Ian,


                                    I took your code
                                    and I ran with it and everything worked out great.


                                    Email me, and I can send it to you and you can try it out, maybe I had something that you didn't?....


                                    I did nothing else spectacular.  So, I am thinking because it worked on my JBoss, that there is something wrong with the way it is deployed on your Glassfish?  I hope to try to deploy on Glassfish a little later tonight, I would be a Glassfish n00b.

                                    1 2 Previous Next