2 Replies Latest reply on Jun 6, 2008 2:18 PM by hispanic

    Rootless value binding for property in POJO

    hispanic

      I have an action class that is intended to process a form submission. In its first iteration, it contained private String fields like so:



      @In(required = false)
      private String firstName;
      
      @In(required = false)
      private String middleName;
      



      and the submitting facelet page had references like so:



      <s:decorate id="first_name_dec" template="input.xhtml">
          <ui:define name="label">First Name</ui:define>
          <h:inputText id="firstName" value="#{firstName}" />
      </s:decorate>
      <s:decorate id="middle_name_dec" template="input.xhtml">
          <ui:define name="label">Middle Name</ui:define>
          <h:inputText id="middleName" value="#{middleName}" />
      </s:decorate>




      Then I decided to refactor and placed the Strings into a simple POJO, like so:



      public class Query  {
          private String firstName;
          private String middleName;
      
          public String getFirstName() {
              return firstName;
          }
      
          public void setFirstName(String firstName) {
              this.firstName = firstName;
          }
      
          public String getMiddleName() {
              return middleName;
          }
      
          public void setMiddleName(String middleName) {
              this.middleName = middleName;
          }
      }




      Then things stopped working like I would assume they should work. I modified my action class to reference the POJO instead of the individual Strings, like so:



      @In(create=true, required = false)
      private Query query;




      and I modified the submitting facelet page like so (prepending the value bindings with query.):


      <s:decorate id="first_name_dec" template="input.xhtml">
          <ui:define name="label">First Name</ui:define>
          <h:inputText id="firstName" value="#{query.firstName}" />
      </s:decorate>
      <s:decorate id="middle_name_dec" template="input.xhtml">
          <ui:define name="label">Middle Name</ui:define>
          <h:inputText id="middleName" value="#{query.middleName}" />
      </s:decorate>




      But this raised the following error:



      javax.el.PropertyNotFoundException: /query.xhtml @24,71 value="#{query.firstName}": Target Unreachable, identifier 'query' resolved to null





      At first, I thought it was stating that the Query object was null. But now I believe it means that query doesn't bind to anything. If I were to place the @Name annotation on the Query class or create a @Factory method for query, it would work. But this is distasteful to me - having to globally namespace a component that may only be used on one page.


      More to the point, why does it appear that value bindings with NO separating dot notation (e.g., {firstName}) implicitly resolve as properties of the target action class, but value bindings WITH a separating dot notation (e.g., {query.firstName}) completely lose that implicit behavior? To me, that is a failing of the framework.


      My workaround is to create a getter and setter for my Query property and modify my value bindings like so (prepending the value bindings with queryAction.):


      <s:decorate id="first_name_dec" template="input.xhtml">
          <ui:define name="label">First Name</ui:define>
          <h:inputText id="firstName" value="#{queryAction.query.firstName}" />
      </s:decorate>
      <s:decorate id="middle_name_dec" template="input.xhtml">
          <ui:define name="label">Middle Name</ui:define>
          <h:inputText id="middleName" value="#{queryAction.query.middleName}" />
      </s:decorate>




      But I don't like the need for the extra getter and setter and verbose value bindings. Is there a way to directly reference a property WITHIN an unnamed POJO field of an action class (just like a top-level String or primitive) that I don't know about? If not, does anyone agree that this would be a beneficial addition to the framework?


      I appreciate any and all feedback. Thanks.


      Environment:



      • JBoss v4.2.2

      • Seam v2.0.2.CR1

      • JBoss Portal v2.6.4

      • PortletBridge v1.0.0.B2





      Mike.....

        • 1. Re: Rootless value binding for property in POJO
          dhinojosa

          You haven't mapped query yet.


          e.g.


          @Name(value="query")
          @Scope(ScopeType.CONVERSATION)
          public class Query  {
              private String firstName;
              private String middleName;
          
              public String getFirstName() {
                  return firstName;
              }
          
              public void setFirstName(String firstName) {
                  this.firstName = firstName;
              }
          
              public String getMiddleName() {
                  return middleName;
              }
          
              public void setMiddleName(String middleName) {
                  this.middleName = middleName;
              }
          }
          



          Of course I would name it something else other than query, something more meaningful, and something that isn't so generic that it easily conflict with another component

          • 2. Re: Rootless value binding for property in POJO
            hispanic

            Dan,


            Thanks for your reply.


            Of course, that's the standard answer - everything has to be named. But I'm trying to avoid that. Query isn't in my Seam project. It resides in a non-Seam project and jar. So it isn't going to have @Name or @Scope annotations. It is simply a POJO, not an entity bean.


            I would think that Seam would provide a more convenient, simple way to access non-Named object properties of an action class from value bindings. Currently, the two alternatives I see are:



            1. getter plus fully-qualified value binding (which, as I showed earlier, is the workaround I have chosen).

            2. creating a Named subclass of my Query class just for Seam's sake, like so:




            @Name(value="query")
            public class QueryForSeamUse extends Query  {
            }




            Neither alternative appears very elegant to me and both require extra work.


            To me, it looks like the value-binding lookup logic works like so:



            • {foo} - No dot, so assume it is a property of the action class.

            • {foo.bar} - Dot, so assume foo is a named component.



            What I'd like to see is for the second case to be extended like so:



            • {foo.bar} - Dot, so assume foo is a named component. If not found, look for foo on the action class.



            Seems logical to me. It would allow for easier re-use of non-annotated classes and avoid learning pains. Frankly, I was thinking that this use-case had already been accounted-for and my frustration was a result of my ignorance of Seam capabilities.