3 Replies Latest reply on Dec 17, 2009 3:35 PM by mikkus70

    Seam Annotations : @In

    aigleborgne
      Hi,

      There is something I don't understand with this annotation.
      I have this component:

      @Name("accueilLotsAction")
      @Scope(ScopeType.CONVERSATION)
      public class AccueilLotsAction implements java.io.Serializable {
              @DataModel("listLots")
              protected List<LotBO> lots;

              @DataModelSelection("listLots")
              @In(create = true) @Out
              protected LotBO lot;

      On my page, it is possible to select a lot from a list, or click "New" to create a new one.
      So, when entering this page, there might be an existing one (if user went to main menu after selecting or creating a lot).

      Seam's documentation says:
      @In
      Specifies that a component attribute is to be injected from a context variable at the beginning of each component invocation. If the context variable is null, an exception will be thrown.

      Because my context variable might be null, I'm adding (create=true)
      As said here:

      @In(create=true)
      Specifies that a component attribute is to be injected from a context variable at the beginning of each component invocation. If the context variable is null, an instance of the component is instantiated by Seam.

      Anyways, no matter what, I get this exception:
      org.jboss.seam.RequiredException: @In attribute requires non-null value: accueilLotsAction.lot

      So, I tried to put (required=false) and got this exception:
      org.jboss.seam.RequiredException: @Out attribute requires non-null value: accueilLotsAction.lot

      I added (required=false) to @Out
      And this works... partially! I got no error on this page.
      But when I click "New" (which do lot = new LotBO(); and call another page), I got an exception in new page:
      @In attribute requires non-null value: lotSaisieAction.lot

      This means that this instruction "lot = new LotBO();" worked but wasn't injected into context by @Out

      I'm completely lost by these annotations.
      Why Create=true didnt work? Why @Out didn't work either?

      Any help would be greatly appreciated.
        • 1. Re: Seam Annotations : @In
          kragoth

          You should not create an instance of a Seam bean using the default constructor.


          In otherwords don't use lot = new LotBO();


          If you do that then Seam does not recognize it as a Seam Bean.
          To instantiate a Seam bean you should use:


          Component.getInstance(...) There are multiple versions of this method so choose whatever one suites you.


          There are other ways of creating new instances as well but this is the one I most commonly use.


          Ultimately just remember if you want a new instance of a Seam bean then you must make sure that Seam makes the new instance not you.


          I'm not entirely sure why the create=true didn't work maybe annotate your LotBO class with @AutoCreate (I doubt this will make a difference but go ahead and try).


          Actually, can you post your code for the LotBO class... there's something else I would like to check.

          • 2. Re: Seam Annotations : @In
            aigleborgne
            Thanks for your explanation.
            I have managed to make it work but I'm not sure it was the best way.
            I used this:
                    @In(required=false) @Out(required=false)
                    protected LotBO lot;

            A first bean with the same previous declaration create an instance with:
            lot = new LotBO();
            In the following bean, I get my new instance. Previously, it wasn't working because I was creating a new instance in the following bean in an init method called by the first bean. I guess Seam was a bit confused of what to do with this object.

            Here is my LotBO:

            @Entity
            @Table(name = "LOT")
            @NamedQueries( {
                            @NamedQuery(name = ALL, query = "from LotBO where typeLot like 'lot' order by dateCreation DESC, idLot DESC"),
                            @NamedQuery(name = ALLBYAUTEURCREATE, query = "from LotBO group by utilisateurCreation.nom, utilisateurCreation.prenom"),
                            @NamedQuery(name = MAXID, query = "select max(idLot) from LotBO") })
            public class LotBO implements java.io.Serializable {

                    private static final long serialVersionUID = 1L;

                    public class QN {
                            public static final String ALL = "LotBO.all";
                            public static final String ALLBYAUTEURCREATE = "LotBO.allByAuteurCreate";
                            public static final String MAXID = "LotBO.maxId";
                    }

                    @Id
                    @GeneratedValue
                    @Column(name = "IDLOT")
                    private Long idLot;
            • 3. Re: Seam Annotations : @In
              mikkus70

              @In(create=true) does not work because Seam cannot create something that is not a component (i.e., that doesn't have a @Name annotation). When you biject something that is not a component, Seam limits itself to retrieve the object instance stored in context. So, @In(required=false is necessary in this case.


              @Out should do its work, possibly it is just outjecting the variable to the event context, so it is destroyed once that context ends. Try overriding the default outjection context with:


              @In(required=false) @Out(required=false, scope=ScopeType.CONVERSATION)
              protected LotBO lot;
              



              By default, @Out should outject to the target's default context or the containing component's scope (but in case of doubt is best to specify it, specially when you're outjecting context variables that are not components).