11 Replies Latest reply on Sep 30, 2008 11:15 PM by ipazmino

    Page param

    ipazmino

      Hi,


      I´m trying to pass a parameter from a list to the editing view.


      In the list, I have a link to make the requestÑ


      <s:link view="/inbox/message.xhtml" value="#{inboxMsg.title}" >
           <f:param name="messageId" value="#{inboxMsg.id}" />
      </s:link>



      At the pages.xml file, I set the expected parameter as


      <page view-id="/inbox/message.xhtml">
               <description>Message #{message.title}</description>
               <param name="messageId" value="#{inboxMsgMngr.message.id}"
           converterId="javax.faces.BigDecimal" />
      </page>



      And, in a stateless bean named inboxMsgMngr, where the actions are defined, I try to get the message as


          @In(required = false)
          @Out(required = false)
          private Message message;



      but when rendering the message.xhtml view the form is empty, and at the messages component the following text is displayed without any exception thrown at the app server.



      model validation failed:javax.el.PropertyNotFoundException: Target Unreachable, 'message' returned null on 'org.javassist.tmp.java.lang.Object_$$_javassist_1'



        • 1. Re: Page param
          gjeudy

          Can you show us the message.xhtml snippet referring to message ?

          • 2. Re: Page param
            ipazmino

            Thanks, this is the message.xhtml file:


            <ui:define name="body">
                 <h:messages globalOnly="true" styleClass="message"/>
            <h:form>
                 <rich:panel>
                      <f:facet name="header">Message Management</f:facet>
                           <s:validateAll>
                                <s:decorate for="txtSubject">
                                     <h:outputLabel for="txtSubject" value="Subject " />
                                     <h:inputText value="#{message.title}" id="txtSubject" required="true" />
                                     <h:message for="txtSubject" />
                                </s:decorate>
                                <rich:calendar id="dateDate" popup="true" value="#{message.datetime}"
                                     locale="US" datePattern="dd/MM/yyyy HH:mm" />
                                <s:decorate for="txtMessage">
                                     <h:outputLabel for="txtMessage" value="Message " />
                                     <h:inputTextarea value="#{message.text}" id="txtMessage" cols="30" rows="5" />
                                     <h:message for="txtMessage" />
                                </s:decorate>
                           </s:validateAll>
                           <h:panelGrid columns="2">
                                <h:panelGroup>
                                     <h:commandButton action="#{inboxMsgMngr.create}" value="Save" rendered="#{message.id == null}"/>
                                     <h:commandButton action="#{inboxMsgMngr.update}" value="Save" rendered="#{message.id != null}"/>
                                </h:panelGroup>
                                <s:button view="/inbox/inbox.seam" value="Close" />
                           </h:panelGrid>
                 </rich:panel>
            </h:form>
            </ui:define>


            • 3. Re: Page param

              So...  you are sending the #{inboxMsg.id} (a BigDecimal I am guessing), with a parameter with name messageId and you expect to receive it a member variable of type Message with name message?


              I don't think that can work. How can it know what should it store in private Message message?


              If you want to read the request parameter  I think you should be using:


              @RequestParameter BigDecimal messageId;
              



              But maybe I am just not getting what are you trying to achieve...

              • 4. Re: Page param
                gjeudy

                How do you populate the message in your inboxmgr? If this is how you populate the Message instance in the Seam context you have to trigger the logic in InboxMgr to instantiate a message and assign it to inboxMgr.message member variable so that it gets outjected

                @Out

                in the context prior to rendering message.xhtml view.


                Alternatively you can use @AutoCreate on the Message class itself (providing it is a seam component) or use a @Factory(message) annotation to get a new instance.

                • 5. Re: Page param
                  ipazmino

                  Thanks a lot for your help.


                  What I'm trying to do is, by passing the message id as a parameter and retrieving it at ths stateless bean, restore the message object that will be outjected, and then injected to persist the updates, but clearly I'm pretty confused. Any advice in how to perform this matter will be mostly welcome.

                  • 6. Re: Page param
                    gjeudy

                    Perhaps reading some Seam reference doc would help? I would read about bijection concept.


                    In a nutshell as Francisco proposed you can probably pass your message id with @RequestParameter annotation, in the action you trigger you use the injected action to load the message object in an @Out variable.


                    Once your message is rendered in the view using the EL expression pointing to your @Out variable. Modify values in your view and submit then you can @In inject again in the backing bean. The action method just needs to get hold of message again and trigger a merge in the database.

                    entityManager.merge(message)

                    .


                    • 7. Re: Page param
                      gjeudy

                      I meant, in the action you trigger you use the injected request parameter to load the message object.

                      • 8. Re: Page param
                        ipazmino

                        Thanks, I kind of merged both of your suggestions!


                        I get the parameter and create the message object


                            @In(required = false)
                            @Out(required = false)
                            private Message message;
                        
                            @RequestParameter
                            private BigDecimal messageId;
                            
                            @Factory("message")
                            public void messageInstance() {
                             log.info("messageId = " + messageId);
                             if (messageId != null) {
                                 message = em.find(Message.class, messageId);
                             }
                            }



                        and the page.xml changed the param definition to


                            <page view-id="/inbox/message.xhtml">
                             <description>Message #{message.title}</description>
                                 <param name="messageId" value="#{inboxMsgMngr.messageId}"
                                      converterId="javax.faces.BigDecimal" />
                            </page>



                        The message gets displayed now, but when pressing the update button it does not invoke the action, nothing happens.


                        <h:panelGroup>
                             <h:commandButton action="#{inboxMsgMngr.create}" value="Save" rendered="#{message.id == null}"/>
                             <h:commandButton action="#{inboxMsgMngr.update}" value="Update" rendered="#{message.id != null}"/>
                        </h:panelGroup>
                        <s:button view="/inbox/inbox.seam" value="Close" />



                        the update method is never invoked, and after pressing the update button, it dissapears. The method doesn't do much


                        public String update() {
                             log.info("message to update = " + message.getId());
                             em.merge(message);
                             FacesMessages.instance().add(FacesMessage.SEVERITY_INFO,
                                  "The message '#{message.title}' was successfully updated.");
                             log.info("updated message = " + message.getId());
                             return "/inbox/inbox.seam";
                            }




                        • 9. Re: Page param

                          I guess you need to configure you class to use ScopeType.PAGE to prevent your private Message message from getting lost. I still do not get why you add @In/@Out for Message message. Maybe you need to configure a <page action=> in the controller of the edit page, in that place you can use the value of the page parameter to query with the entityManager and get the object from the database, then you can store it in member variable... and that should be it.

                          • 10. Re: Page param
                            gjeudy

                            Try sticking a

                            <h:messages />

                            in your xhtml to display JSF validation/error messages.


                            It could be that your form post didnt pass PROCESS_VALIDATIONS phase.

                            • 11. Re: Page param
                              ipazmino

                              I don't think I can scope a stateless bean PAGE, can I?
                              I annotated Message message as @In and @Out because This is the object I'm using to show load up the view, and to save the state to persist. By using the factory, don't I need anymore to annotate it with @In?


                              I do have a

                              <h:messages />

                              component declared, but doesn't show anything when updating.


                              <h:messages globalOnly="true" styleClass="message"/>