5 Replies Latest reply on Jul 10, 2008 6:47 PM by Dan Allen

    pages.xml: what is the <in> tag meant for?

    Vivian Steller Newbie

      Very short question: what is the <in/> meant for? I couldn't find any documentation on this tag of the pages.xml file.


      I tried to use it, but unfortunately it does not seem to do what I expected. Has someone used it/has a use case for it? Does it work?


      Thanks in advance,
      vivian

        • 1. Re: pages.xml: what is the <in> tag meant for?
          Thor Kummer Newbie
          I'm also curious as to what <in/> is for. Is it an in-only version of the <param/> tag? If so why are there no converter and validator attributes? Or is it meant to allow assignment of values to properties of arbitrary components? E.g.:

            <in name="myContext.pageValidator" value="#{myPageValidator}"/>

          I was hoping for this answer as it would have allowed me to specifying a page level validator. But I couldn't get it to work that way.

          Or is it simply a left-over from non-implemented feature?
          • 2. Re: pages.xml: what is the <in> tag meant for?
            Dan Allen Master

            It's implemented, it is just really ecclectic. I didn't cover it in Seam in Action because I barely understand when to use it. Basically, think of it like a page parameter. For <in>, it looks up a component by name (the name attribute) and assigns it to the value expression (the value attribute). The <out> does evaluates the value expression (the value attribute) and creates a context variable (the name attribute).


            Basically, you should only use this feature under a very special case. It is one of those if you have to ask, then someone else will too features. Just because you can do it, doesn't mean you should. Unless you convince me otherwise, stay away from this feature.

            • 3. Re: pages.xml: what is the <in> tag meant for?
              Vivian Steller Newbie

              Thanks dan!


              Well, I have a usecase for it (but maybe it's just a lack of my app design?). Consider the following scneario:


              I've a facelet page (/semester/create.xhtml) that displays a form for a Semester entity. It looks similar to this:


              <h:form id="semesterForm">
              ...   
                        <h:outputLabel value="#{messages.semesterType}" for="semesterType"/>
                        <h:selectOneMenu id="semesterType" value="#{semester.semesterType}" required="true">
                            <s:selectItems .../>
                        </h:selectOneMenu>
                        
                        <h:commandButton value="#{messages.createbutton}" action="#{createSemester.execute}"/>
              ...
              </h:form>



              #{semester...} refers to a JPA entity that should be filled and stored via the conversation scoped CreateSemesterAction component (which is named createSemester). However, I do not define semester as a Seam Component itself but it shall be outjected from a getter method of the CreateSemesterAction so that I can simply use #{semester...} notation instead of each time writing #{createSemester.semester...}. Another reason is that I want to re-use the form for the edit action, thus I don't want to couple the view to the createSemester component.


              To accomplish that, my CreateSemesterAction looks as follows:


              @Name("createSemester")
              @Scope(ScopeType.CONVERSATION)
              @Transactional
              public class CreateSemesterAction implements Serializable {
              
                  ...
              
                  @Create
                  public void init() {
                      semester = new Semester();
                      subscriptionDuration = new SubscriptionDuration();
                  }
              
                  public void prepare() {
                      /* placeholder to expose context variables */
                  }
                  
                  
                  public String execute() {
                    // logic to store the newly created semester
                  }
                  
                  @Out
                  public Semester getSemester() {
                      return semester;
                  }
                  
                  @In
                  public void setSemester(Semester semester) {
                      this.semester = semester;
                  }
              }



              My pages.xml snippet for that view looks as follows:



                  <page view-id="/semester/create.xhtml" action="#{createSemester.prepare()}">
                    <begin-conversation join="true"/>
                    <navigation>...</navigation>
                  </page>



              The odd thing about this is that the semester bean is only outjected when the CreateSemesterAction was hitted somehow. That means, I have to call the pretty much useless createSemester.prepare() method just to make Seam outject the semester.


              Now, I think of dropping the action call to createSemester.prepare() but instead using <out/> (or I misunderstood <in/> is to be used). So I tried putting the following line into the pages.xml:


              <out name="semester" value="#{createSemester.semester}"/>



              However, this does not work. But again, I think it's maybe bad application design. Any suggestions appreciated!
              Thanks!

              • 4. Re: pages.xml: what is the <in> tag meant for?
                Dan Allen Master

                Okay, a couple of things here. First and foremost, <out> can only be used when you navigate (a navigation rule is invoked). Therefore, it wouldn't be of any use on an initial request (without some clever page action hacks). Normally, this is a classic case for a factory.


                @Name("createSemester")
                @Scope(ScopeType.CONVERSATION)
                @Transactional
                public class CreateSemesterAction implements Serializable {
                    ...
                    @Factory("semester")
                    public Semester getSemester() {
                        return semester;
                    }   
                }



                In that case, you don't need the @Out since the semester is pulled rather than pushed. But you have the problem that you want to reuse the edit page but not the action bean (the factory can only be on one of the two beans). In that case, it may seem silly, but the page action is the way to go. It might have no body, but it's still performing work (performing work declaratively in this case). So you are basically doing the right thing. As I say in Seam in Action, a page action let's you force bijection to occur on an initial request.

                • 5. Re: pages.xml: what is the <in> tag meant for?
                  Dan Allen Master

                  Btw, one day, you might find that you do need to perform login inside of prepare(), in which case you are all setup to do so.