10 Replies Latest reply on Feb 2, 2007 8:40 AM by Gavin King

    Simple application component

    Mike Quilleash Newbie

      Using Seam 1.1.0.GA

      I have a simple Seam component which is just for injecting a singleton session factory and a ManagedHibernateSession that uses it. (I'm aware of the HibernateSessionFactory component but I think this problem is more general).

      First the session factory wrapper component.

      @Name( "referenceSessionFactory" )
      @Scope( ScopeType.APPLICATION )
      @Intercept( InterceptionType.NEVER )
      public class ReferenceSessionFactory
      {
       @Unwrap
       public SessionFactory getSessionFactory()
       {
       return HibernateSession.getSessionFactory();
       }
      }
      


      And a test component

      @Name( "test1" )
      @Scope( ScopeType.EVENT )
      public class Test1
      {
       @In( create = true )
       private Session referenceSession;
      
       @Create
       public void init()
       {
       int i = 1;
       }
      
       public String getStr()
       {
       return "test1";
       }
      }
      


      and the components.xml piece.

       <!-- reference session factory wrapper component -->
       <component class="com.azure.spark.web.seam.component.ReferenceSessionFactory" auto-create="true"/>
      
       <!-- managed session from the reference session factory -->
       <core:managed-hibernate-session name="referenceSession" session-factory="#{referenceSessionFactory}"/>
      
       <component class="com.azure.spark.web.bean.security.Test1"/>
      


      And my simple test 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></title>
       </head>
       <body>
       <h:outputText value="#{test1.str}"/>
       </body>
      </html>
      


      Now if I request a page that references the test1 component str property I get the following error.

      java.lang.IllegalStateException: SessionFactory not found
       at org.jboss.seam.core.ManagedHibernateSession.getSessionFactoryFromJndiOrValueBinding(ManagedHibernateSession.java:156)
       at org.jboss.seam.core.ManagedHibernateSession.createSession(ManagedHibernateSession.java:81)
       at org.jboss.seam.core.ManagedHibernateSession.create(ManagedHibernateSession.java:69)
      


      If I remove the @Create annotation from the test1 component then it works as expected (page just renders "test1").

      It seems that there is some problem creating and injecting the hibernate session when it is the @Create method that is being intercepted (I can see the Component.callCreateMethod() further down in the stack trace). I haven't seen this problem injecting other components, facesContext and the referenceSessionFactory seem to work fine.

      More interestingly if I visit the test page it fails as above. If I visit a different page that has a hibernate session injected and no @Create it works fine. Then if I go back and refresh the test page the error changes to...

      java.lang.ClassCastException: com.azure.spark.web.seam.component.ReferenceSessionFactory
       at org.jboss.seam.core.ManagedHibernateSession.getSessionFactoryFromJndiOrValueBinding(ManagedHibernateSession.java:153)
       at org.jboss.seam.core.ManagedHibernateSession.createSession(ManagedHibernateSession.java:81)
       at org.jboss.seam.core.ManagedHibernateSession.create(ManagedHibernateSession.java:69)
      


      Which looks like it's finding something but it returns the Seam component itself rather than the result of the @Unwrap function. This is also when intercepting the call to the @Create method of test1.

      Appreciate any advice on whether I'm doing something wrong or if this is a possible bug.

      Cheers.

      Mike.

        • 1. Re: Simple application component
          Gavin King Master

          So, I started with the hibernate2 example, modified components.xml to look like this:

          <core:hibernate-session-factory name="hibernateSessionFactory"/>
          
           <core:managed-hibernate-session name="bookingDatabase"
           session-factory="#{hibernateSessionFactory}"
           auto-create="true"/>
          


          And then added an @Create method to HotelSearchingAction.

          Everything works perfect.

          AFAICT, this is equivalent to your setup, no?

          • 2. Re: Simple application component
            Gavin King Master

            BTW, this line in your components.xml is redundant:

            <component class="com.azure.spark.web.bean.security.Test1"/>


            • 3. Re: Simple application component
              Gavin King Master

              Question: does adding @Startup to ReferenceSessionFactory fix it?

              • 4. Re: Simple application component
                Mike Quilleash Newbie

                Thanks for looking into this.

                Adding @Startup makes the initial

                java.lang.IllegalStateException: SessionFactory not found
                


                Error stop happening. Instead I immediatly get the

                java.lang.ClassCastException: com.azure.spark.web.seam.component.ReferenceSessionFactory
                


                on the first request of the page. Should I have the @Startup on a component like this?


                Differences between the hibernate 2 examples and mine I can see:

                I use hibernate3 rather than hibernate2 (probably doesn't matter)

                That components.xml uses a core:hibernate-session-factory which uses a method for creation whereas mine is just a component.

                I have auto-create="true" on the referenceSessionFactory component whereas the h2 example does not.

                I don't have auto-create="true" on the managed-hibernate-session, I use create="true" in the @In where it is used.


                I have to duck out for a couple of hours now but I'll do some more investigation when I get back. I'll try moving my configuration closer to the hibernate2 example and see if it starts working when I change something.

                Cheers.


                • 5. Re: Simple application component
                  Gavin King Master

                   

                  Should I have the @Startup on a component like this?


                  Not especially, I'm just eliminating a difference b/w the two examples.


                  That components.xml uses a core:hibernate-session-factory which uses a method for creation whereas mine is just a component.


                  huh? the two things are equivalent. try changing it to a

                  I have auto-create="true" on the referenceSessionFactory component whereas the h2 example does not.


                  irrelevant


                  I don't have auto-create="true" on the managed-hibernate-session, I use create="true" in the @In where it is used.


                  also irrelevant

                  • 6. Re: Simple application component
                    Mike Quilleash Newbie

                    OK found the following so far. Think I've got to the bottom of the ClassCastException tho I'm still not sure whether

                    The @Startup annotation means that the Component.newInstance() gets called at the end of the seam initialisation which creates a mapping of

                    "referenceSessionFactory" -> Component( referenceSessionFactory )

                    in the application context/scope. Unfortunately when the ManagedHibernateSession comes to evaluate #{referenceSessionFactory} the JSF (RI) ScopedAttributeELResolver gets in first and returns the value in the application scope which is the component itself, rather than the unwrapped SessionFactory.

                    Not sure why this only happens when the @Create method is being called. I found that outside the @Create method then the SeamVariableResolver gets first go at resolving the "referenceSessionFactory" and presumably does the proper unwrapping. Is this VariableResolver perhaps not enabled until after the @Create method is called?

                    I'll continue looking around.

                    Cheers.

                    Mike.

                    • 7. Re: Simple application component
                      Mike Quilleash Newbie

                      Bit of my post got lost there. First line should read...

                      OK found the following so far. Think I've got to the bottom of the ClassCastException tho I'm still not sure whether it's a configuration problem or a bug.

                      ... ctd

                      • 8. Re: Simple application component
                        Gavin King Master

                        Do you have the following in faces-config.xml:

                        <application>
                         <el-resolver>org.jboss.seam.jsf.SeamELResolver</el-resolver>
                        </application>


                        As described here:

                        http://docs.jboss.com/seam/1.1.5.GA/reference/en/html/configuration.html

                        • 9. Re: Simple application component
                          Mike Quilleash Newbie

                          That's fixed it thanks! A case of RTFM (more carefully). I saw it commented out in the Seam faces-config.xml but assumed it was an old piece of code.

                          Would it break anything else to enable this by default as I'm probably not the only one who will trip up on this?

                          Thanks again for your time.

                          Mike.

                          • 10. Re: Simple application component
                            Gavin King Master

                            Cant enable it be default because it is a JSF 1.2 feature.