4 Replies Latest reply on Feb 8, 2007 5:16 AM by Mike Quilleash

    bijection value causing JSF Error.  Misuse, or misunderstand

    James Hays Novice

      I'm getting the following error reported from JSF in certain situations. I have found a solution, but I wanted to dump out my code to the group to see if you guys have seen this issue and help me determine if this is an issue in seam, or if I'm just misusing or not understanding this particular concept.

      What I have is a simple form application. This particular piece is a search form. I simply want to submit my form, have seam inject it into my bean component, which is an entity bean, and complete an action. Simple stuff. I'm not doing anything crazy or extreme here. Let me show you the code that does work and then I'll make a simple modification to show what doesn't work.

      First, let's look at my Entity Bean.

      @Entity
      @Name("profileRecord")
      public class ProfileRecord implements Serializable {
      
       @Id
       @GeneratedValue
       private long id;
      
       private String workAuthorizationNumber;
       private String proposalNumber;
      }
      

      This is a simple 3 field bean. I've removed the getters/setters from this posting.

      My listener looks like this:
      @Name("search")
      @Stateless
      public class SearchAction implements Search
       {
       @Logger
       private Log log;
      
       @In(required=false)
       private ProfileRecord profileRecord;
      
       public String search()
       {
       log.info("Running Search");
       return null;
       }
      }
      

      And, my xhtml.
       <h:form>
       <h2>Basic Search</h2>
       <div style="text-align: right;"><label>WA #:<h:inputText value="#{profileRecord.workAuthorizationNumber}" /></label></div>
       <div style="text-align: right;"><label>Proposal #:<h:inputText value="#{profileRecord.proposalNumber}" /></label></div>
       <div style="text-align: right;"><h:commandButton type="submit" value="Search" action="#{search.search}" /></div>
       <div style="text-align: right;"><a href="detailedSearch.seam">Detailed Search</a></div>
       </h:form>
      

      This code works as expected. My issues arise when I change the field name in my action listener. My understanding is that I should be able to modify my action listener to have a differently named variable for profileRecord. I should be able to do that either by writing
       @In(required=false)
       private ProfileRecord searchRecord;
      

      or
       @In(value="searchRecord", required=false)
       private ProfileRecord profileRecord;
      

      And then changing my xhtml to
       <h:form>
       <h2>Basic Search</h2>
       <div style="text-align: right;"><label>WA #:<h:inputText value="#{searchRecord.workAuthorizationNumber}" /></label></div>
       <div style="text-align: right;"><label>Proposal #:<h:inputText value="#{searchRecord.proposalNumber}" /></label></div>
       <div style="text-align: right;"><h:commandButton type="submit" value="Search" action="#{search.search}" /></div>
       <div style="text-align: right;"><a href="detailedSearch.seam">Detailed Search</a></div>
       </h:form>
      

      If I make any of those changes and deviate from my original example, I get the error stating.
      value could not be converted to the expected type

      I'm taking this as a JSF error and not a seam error based on a previous thread replied to by Gavin that stated that this particular error string was coming from JSF. I can't find that thread back at the moment though. Sorry.

      Am I misunderstanding the purpose and the abilities of injection here? My understanding is that each injection or outjection (bijection) dumps these components in a type of component cloud that other components can pull from or put to. If I specify a value for a bijection annotation, that name is what is stored as the link to that component. If I don't specify a value, the field name is used as default. Which would lead me to believe that all three of my examples should work the same.

      Please, help clarify my understanding here. I've searched the forums and Google and have had limited success in finding anything regarding this issue. I've also looked in the demos and have seen numerous times where the examples do what I'm doing and it has worked as expected, yet mine will not.

      Thanks,
      James

        • 1. Re: bijection value causing JSF Error.  Misuse, or misunders
          Mike Quilleash Newbie

          I believe that Seam is not finding your component after the change.

          Your component has @Name("profileRecord") so it is always accessed via this name.

          The value on the @In is for when your variable name does not match the Seam component name. So using your example I think this would work

          @In( value="profileRecord" )
          private ProfileRecord searchRecord;

          Here you're saying "although my field is called searchRecord, the actual component I want to inject is called profileRecord".

          HTH.

          • 2. Re: bijection value causing JSF Error.  Misuse, or misunders
            James Hays Novice

            Thanks for the reply. I'm still having issues though. I changed my searchAction to contain

             @In(value="profileRecord", required=false)
             private ProfileRecord searchRecord;
            


            if my xhtml contains
             <div style="text-align: right;"><label>WA #:<h:inputText value="#{searchRecord.workAuthorizationNumber}" /></label></div>
             <div style="text-align: right;"><label>Proposal #:<h:inputText value="#{searchRecord.proposalNumber}" /></label></div>
            

            I continue to get the value cannot be converted error. which makes sense to me.

            if I leave the xhtml to read
             <div style="text-align: right;"><label>WA #:<h:inputText value="#{profileRecord.workAuthorizationNumber}" /></label></div>
             <div style="text-align: right;"><label>Proposal #:<h:inputText value="#{profileRecord.proposalNumber}" /></label></div>
            

            It seems to work.

            If I understand this correctly, there will be no way for me to inject a property named searchRecord of type ProfileRecord into an action from my xhtml. My xhtml will always have to represent the ProfileRecord entity by specifying #{profileRecord.blah}. This just doesn't seem right.

            How can I represent two different entity components on the same page in the same scope? One option would be to create them in a factory to create a default object so it is already as a component. That seems noisy though. Along those lines, I would think I could also specify
            @In(create=true)
             private ProfileRecord searchRecord;
            in my action and then use #{searchRecord} in my xhtml, but that doesn't seem to work either. I still get the value could not be created error.

            I'm assuming that I am still missing something critical.

            Thanks.

            • 3. Re: bijection value causing JSF Error.  Misuse, or misunders
              Pete Muir Master

              Use @Role on the entity bean.

              • 4. Re: bijection value causing JSF Error.  Misuse, or misunders
                Mike Quilleash Newbie

                I think you've kinda got it a bit backward. Basically Seam has a big map of components that are available. These components are defined either in components.xml with or more usually with the @Name annotation.

                For accessing pure components these are the only names that are available for you to use in EL and for injection via @In. So you can't put #{searchRecord.xxx} in an EL expression because there is no component called searchRecord. Similarly @In looks for components by using the field/method name unless it is specified explicitly by @In( value="" ).

                To get your example to work you have to leave the name as profileRecord in the .xhtml or use some method of creating a profileRecord alias. Putting <factory auto-create="true" name="searchRecord" value="#{profileRecord}"/> would probably have the effect you are after.

                It sounds like you might be trying to achieve something similar to what I am at the moment. I'm trying to create a searchTemplate.xhtml facelet template that wraps all the common layout and action hooks of a standard search screen (parameters, grid, search button, rows returned display, pagination buttons etc). Then I'll use the template in a real view page and just populate the parameter grid and data grid definition. On the model side I want to implement all the common logic and magic in a reusable component and allow overriding with custom logic per page (custom validation, grid population etc).

                So I want do have component per search screen but then access the current search screen in my search template with #{searchBean}.

                If anyone has any experience doing this I'd be interested to hear about it.