9 Replies Latest reply on Mar 19, 2008 8:47 PM by norman

    Outjecting non seam components

    toni

      Hi,


      does every component require the @Name annotation, in order to be outjected into one of the seam contexts?


      So I'm asking, if this is legal stuff or if it's breaking any of seam's framework contracts?


      @Out
      String name
      
      @Out
      List list = new ArrayList();
      
      @Out
      Integer someNumber = new Integer(1);
      


        • 1. Re: Outjecting non seam components
          wrzep

          Well, yes, all your examples are correct. Actually, I think that it was easy to test it by yourself ;)


          -P

          • 2. Re: Outjecting non seam components
            toni

            There is a difference between whether or not it's possible and if it's actually correct.


            Because since seam 2.x I have not been able to directly outject a DataModel anymore and initalize it through a page event.


            It used to be possible to outject a DataModel without using a DataModel annotation like this:


            @Out(required = false)
            DataModel dataModel;
            
            



            However, this is not working anymore, if you load some data through a page event. I run into an exception.


            Using


            @DataModel
            List list
            



            works fine. I don't know why outjecting the DataModel and initalizing it rhourg a page event causes problems.


            That's why I asked if one can generally outject any class/object or if it has to be a seam component.

            • 3. Re: Outjecting non seam components
              wrzep

              Tim Peters wrote on Mar 02, 2008 06:39 PM:

              However, this is not working anymore, if you load some data through a page event. I run into an exception.

              Weird.

              Stack trace?

              -P

              • 4. Re: Outjecting non seam components
                toni

                Hi Pawel,


                actually I was wrong saying that it's throws an exception. But it does not work. The DataModel gets outjected, but it's empty.


                You can try the following code. Call the jsp page and then look at the variable other. It will be always empty.


                pages.xml


                <?xml version="1.0" encoding="UTF-8"?>
                <pages xmlns="http://jboss.com/products/seam/pages"
                       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                       xsi:schemaLocation="http://jboss.com/products/seam/pages http://jboss.com/products/seam/pages-2.0.xsd">
                
                  <page view-id="/test.jsp" action="#{testAction.loadData}">
                    <begin-conversation join="true"/>
                  </page>
                
                </pages>
                



                SFSB


                package de.test.calc.workflow;
                
                import de.test.calc.model.TestEntity;
                import org.jboss.seam.annotations.Destroy;
                import org.jboss.seam.annotations.In;
                import org.jboss.seam.annotations.Name;
                import org.jboss.seam.annotations.Out;
                import org.jboss.seam.jsf.ListDataModel;
                
                import javax.ejb.Remove;
                import javax.ejb.Stateful;
                import javax.faces.model.DataModel;
                import javax.persistence.EntityManager;
                import javax.persistence.Query;
                
                
                @Stateful
                @Name("testAction")
                
                public class TestAction implements TestActionInterface
                {
                  @In(create = true)
                  EntityManager entityManager;
                
                  @Out(required = false)
                  DataModel other;
                
                  @In(create = true)
                  TestEntity testEntity = new TestEntity();
                
                  public String loadData()
                  {
                    runQuery(entityManager.createQuery("SELECT t FROM TestEntity t"));
                    return "test";
                  }
                
                  protected void runQuery(Query query)
                  {
                    other = new ListDataModel();
                    other.setWrappedData(query.getResultList());
                  }
                
                  public String save()
                  {
                    entityManager.merge(testEntity);
                    testEntity = new TestEntity();
                    return "test";
                  }
                
                  @Remove
                  @Destroy
                  public void destroy()
                  {
                  }
                
                }
                



                Interface


                package de.test.calc.workflow;
                
                import javax.ejb.Local;
                import javax.faces.model.DataModel;
                
                
                @Local
                
                public interface TestActionInterface
                {
                  public String loadData();
                  public void destroy();
                    public String save();
                }
                



                Entity Bean


                package de.test.calc.model;
                
                import org.jboss.seam.annotations.Name;
                
                import javax.persistence.Entity;
                import javax.persistence.GeneratedValue;
                import javax.persistence.GenerationType;
                import javax.persistence.Id;
                import javax.persistence.Lob;
                import java.io.Serializable;
                
                
                @Entity
                @Name("testEntity")
                
                public class TestEntity implements Serializable
                {
                  @Id
                  @GeneratedValue(strategy = GenerationType.IDENTITY)
                  long id;
                  
                  @Lob
                  String subject;
                  @Lob
                  String body;
                
                  public long getId()
                  {
                    return id;
                  }
                
                  public void setId(long id)
                  {
                    this.id = id;
                  }
                
                  public String getSubject()
                  {
                    return subject;
                  }
                
                  public void setSubject(String subject)
                  {
                    this.subject = subject;
                  }
                
                  public String getBody()
                  {
                    return body;
                  }
                
                  public void setBody(String body)
                  {
                    this.body = body;
                  }
                
                
                  public boolean equals(Object o)
                  {
                    if (this == o) return true;
                    if (o == null || getClass() != o.getClass()) return false;
                
                    TestEntity that = (TestEntity) o;
                
                    if (id != that.id) return false;
                
                    return true;
                  }
                
                
                  public int hashCode()
                  {
                    return (int) (id ^ (id >>> 32));
                  }
                
                }
                

                • 5. Re: Outjecting non seam components
                  wrzep

                  Have you tried the same scenario with something different than DataModel (e.g. String)? Maybe your query returns empty result list.

                  -Pawel

                  • 6. Re: Outjecting non seam components
                    toni

                    Well a variable of type String works, but not of type DataModel. That's why I posted this question, because it doesn't work in this particular case.


                    I have used a debugger and you can see that the records are created and fetch from the database. Also the DataModel contains them shortly just before the page is rendered.


                    After that they disappear, when you look into at the conversation.  So something goes wrong with outjecting them. If you use a @DataModel with a List, then everything works as expected.


                    So I thought, maybe outjecting non seam components, by that I mean ones which have not been tagged with the @Name annotation might be outjected, but actually should not, because of unexpected behaviour.


                    Actually I think I have noticed something like this with Enumerations.

                    • 7. Re: Outjecting non seam components
                      wrzep

                      OK, I've tested it myself. It really doesn't work with DataModel type.  You may want to open new jira request, but personally I can see no reason not to use @DataModel annotation here :-)



                      Actually I think I have noticed something like this with Enumerations.

                      Works fine for me.

                      -Pawel

                      • 8. Re: Outjecting non seam components
                        toni

                        You are right that it makes not much sense to use it direclty.


                        But I was just wondering, why it does not work and thought, maybe you can only outject components which are seam components.

                        • 9. Re: Outjecting non seam components
                          norman

                          On the datamodel side, the short story here is that if you use a DataModel from a conversation scope, Seam will manage it such that the DataModel is correct when the owning component is active but isn't valid when it isn't.


                          Obviously a datamodel is meant to be shared.  If you do that using @Out to push the DataModel object out of the class, then you need to do an @In to complete the link.  When Seam sees the @In, it knows that the DataModel state is public and will manage it differently.


                          I'm looking through the code to see if there is a better way we can do this, but for the time being just add @In(required=false) to your manually managed @Out DataModel.