8 Replies Latest reply on Dec 15, 2006 9:24 AM by quilleashm

    Event scoped component accessing Conversion scope

      I have a search component which is event scoped. Itself it just has four properties which are bound to four input fields in my JSF page.

      It extends a generic search component which has a hibernate session which is injected by the @In( create = true ) from the ManagedHibernateSession component. This generic component has bindings to a couple of the controls on the JSF page (grid/parameter panel etc).

      The search renders fine when it is visited the first time, including some db queries to get some meta-information. On clicking the search button which posts back the @In injection of the Session fails because the bijection gets fired when binding the UI components to the search object. This happens during the restore view phase when the conversation scope is not available and therefore neither is the hibernate session.

      I get the feeling I'm just not using it right but I'm not sure why. Is injecting conversation scoped components into event scoped components something that shouldn't/can't be done? Or do I have my components badly designed.

      I've posted the highlights of the classes here..

      The component

      @Name( "elementSearch" )
      @Scope( ScopeType.EVENT )
      public class ElementSearch extends SparkSearch
      {
       // control value bindings
       private String eltName;
       private Integer elementSet;
       private Integer country;
       private String eltDigits;
      
       public String getEltName()
       {
       return eltName;
       }
      
       // ... more getters/setters here
      


      public abstract class SparkSearch
      {
       private UIData dataGrid;
       private HtmlPanelGrid parameterGrid;
      
       @In( create = true )
       private Session referenceSession;
      
       @In( required = true )
       private SessionFactory referenceSessionFactory;
      
       public HtmlPanelGrid getParameterGrid()
       {
       return parameterGrid;
       }
      
       public void setParameterGrid( HtmlPanelGrid parameterGrid )
       {
       // this gets called during the restore-view phase at which point the bijection fails on the referenceSession
       this.parameterGrid = parameterGrid;
       }
      
       // .. more getters/setters here + action methods
      


      Any comments appreciated.

      Cheers.

      Mike.

        • 1. Re: Event scoped component accessing Conversion scope
          pmuir

          I think its not-so-normal to bind the JSF components directly - instead use value binding (value=#{foo.bar}") (especially if you use facelets).

          You should e able to inject components of any scope into a component of any scope with no problems.

          • 2. Re: Event scoped component accessing Conversion scope

            Done some more investigation into this. I have a minimal test case.

            JSF page

            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE html
             PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
             "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            <html xmlns="http://www.w3.org/1999/xhtml"
             xmlns:ui="http://java.sun.com/jsf/facelets"
             xmlns:f="http://java.sun.com/jsf/core"
             xmlns:h="http://java.sun.com/jsf/html">
             <head>
             <title>Element Name Search</title>
             </head>
             <body>
             <h:form>
             <h:inputText value="#{elementSearchAction.searchString}" binding="#{elementSearchAction.searchStringInput}" />
             <h:commandButton value="Search" action="#{elementSearchAction.find}"/>
             </h:form>
             </body>
            </html>
            


            Action component

            @Name( "elementSearchAction" )
            @Scope( ScopeType.EVENT )
            public class ElementSearchAction
            {
             @In( create = true )
             private Session referenceSession;
            
             private String searchString = "";
            
             private UIInput searchStringInput;
            
             public void find()
             {
             referenceSession.createQuery( "from Element where eltName like :eltName" ).setParameter( "eltName", searchString + "%" ).list();
             }
            
             public String getSearchString()
             {
             return searchString;
             }
            
             public void setSearchString( String searchString )
             {
             this.searchString = searchString;
             }
            
             public UIInput getSearchStringInput()
             {
             return searchStringInput;
             }
            
             public void setSearchStringInput( UIInput searchStringInput )
             {
             this.searchStringInput = searchStringInput;
             }
            }
            


            The problem happens when a post-back is done to the page (hit the search button) and the restore view phase calls through to setSearchStringInput() to bind the control to the bean. At this point the Seam bijection interceptor jumps in and tries to populate the referenceSession but because the conversation context is not active yet it fails to do this.

            Removing the binding of the input control and the form works fine on a post-back.

            Changing the action to be conversation scoped gives this..

            binding="#{elementSearchAction.searchStringInput}": Target Unreachable, identifier 'elementSearchAction' resolved to null
            


            presumably because the restore view phase is trying to do this binding but the conversation scope is not active yet.

            I definately need to bind controls into the beans to do dynamic manipulation of controls. Do I need to rethink my component structure? Or something else? Is deferring seam bijection until after the restore view phase a possibility?

            Cheers.

            Mike.

            • 3. [Resolved] Re: Event scoped component accessing Conversion s

              Found the @Intercept annotation which I can apply to my search bean.

              Setting this...

              @Name( "elementSearchAction" )
              @Scope( ScopeType.EVENT )
              @Intercept( InterceptionType.AFTER_RESTORE_VIEW )
              public class ElementSearchAction
              {
               ...
              


              Stops all interception during the restore view phase so my controls get bound without firing the @In injections.

              Cheers.

              Mike.



              • 4. Re: Event scoped component accessing Conversion scope
                gavin.king

                Try @Intercept(AFTER_RESTORE_VIEW)

                But what exactly is the exception you get?

                • 5. Re: Event scoped component accessing Conversion scope

                  In this function in Component

                  private Object getInstanceToInject(In in, String name, Object bean, boolean enforceRequired)

                  The if condition at the bottom evals to true

                   if ( result==null && enforceRequired && in.required() )
                   {
                   throw new RequiredException(
                   "In attribute requires value for component: " +
                   getAttributeMessage(name)
                   );
                   }
                  


                  Having said that, it seems theres a small bug in the DebugPageHandler.handle( Exception e ) method as the exception above gets thrown and trapped by this handler but then you get a null pointer on the first call to the conversation context.

                  conversationContext.set("org.jboss.seam.debug.lastException", e);
                  


                  As the conversation context isn't created yet. Probably just needs an if null check wrapping round this.



                  • 6. Re: Event scoped component accessing Conversion scope
                    gavin.king

                    Well use required=false then!

                    What version of Seam gives you a problem on the debug page? I think if you go and download the GA release it is fixed.

                    • 7. Re: Event scoped component accessing Conversion scope

                      I think this means you can't have a conversation scoped component with UI component bindings. At the moment the setters for any binding="" get called during the restore view phase at which point the conversation scope is not valid.

                      Is there any way round this or plans to address this in the future?

                      Cheers.

                      Mike.

                      • 8. Re: Event scoped component accessing Conversion scope

                        I'll check the debug handler exception when I download the 1.1 release shortly.

                        Cheers.

                        Mike.