Announcement Announcement Module
Collapse
No announcement yet.
Stateful Gilead Spring-Flex RC1 Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Stateful Gilead Spring-Flex RC1

    I'm trying to integrate the gilead hibernate adapter (1.2.2.598) in our project.
    Thanks to the new RC1 of the spring-flex project you can create a custom Java Adapter via the ManageableComponentFactoryBean:

    Code:
    <bean id="hibernate-object"
    		class="org.springframework.flex.core.ManageableComponentFactoryBean">
    		<constructor-arg value="net.sf.gilead.blazeds.adapter.PersistentAdapter" />
    		<property name="properties" >
    			<value>
    				{"persistence-factory":
    					{"class":"net.sf.gilead.core.hibernate.spring.HibernateSpringUtil",
    				 	 "singleton" :"true", 
    					 "method":"getSessionFactory"
    					},
    				 "stateless":"false"
    				} 
    			</value>
    		</property>
    	</bean>
    	
    	<flex:message-broker>
    		<flex:remoting-service default-adapter-id="hibernate-object"/>
    	</flex:message-broker>
    However, when I put previous code in my applicationContext.xml I get a
    Code:
    java.lang.RuntimeException: getSessionFactory' method for singleton net.sf.gilead.core.hibernate.spring.HibernateSpringUtil returns null !
            at net.sf.gilead.blazeds.adapter.PersistenceUtilManager.createUtilFromHelper(PersistenceUtilManager.java:249)
    I know that it's a NPE thrown by Gilead, but I have a feeling there is something wrong with my spring config.
    Is there something missing from my spring-flex configuration?

    Thanks in advance.

  • #2
    How are you setting up Hibernate in your application context? I've not looked at that HibernateSpringUtil class to see how it is looking up the Hibernate session, but that looks to be the root of the problem, that it is not finding the session. Perhaps Hibernate has not yet been initialized by Spring. If that is the case, specifying that the "hibernate-object" bean depends on whichever AbstractSessionFactoryBean subclass you are using should do the trick.

    Comment


    • #3
      If I understand your reply correctly...

      We are using the following AbstractSessionFactoryBean:
      Code:
      <bean id="sessionFactory"
      		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
      ...
      </bean>
      However adding:
      depends-on="sessionFactory" to our hibernate-object bean doesn't work.

      Comment


      • #4
        Ok, I've looked at their source a little, and it looks like you've got to do things a bit differently. The HibernateSpringUtil class seems to be meant for providing the SessionFactory to Gilead, but it doesn't actually know how to locate the SessionFactory. It looks like there are several ways you could go about this, none of which are particularly elegant.

        The PersistentAdapter and HibernateSpringUtil really don't look like they were designed with each other in mind. The first thing I think you'll need to do it extend HibernateSpringUtil and override the getInstance() method so that it actually returns an instance of your custom HibernateSpringUtil instead of HibernateUtil. Once you've done that, I think something like the following should work:

        Code:
        <bean id="gileadUtil" class="com.foo.CustomHibernateSpringUtil" 
            factory-method="getInstance">
            <property name="sessionFactory" ref="mySessionFactory" />
        </bean>
        
        <bean id="hibernate-object" depends-on="gileadUtil"
            class="org.springframework.flex.core.ManageableComponentFactoryBean">
            <constructor-arg value="net.sf.gilead.blazeds.adapter.PersistentAdapter" />
            <property name="properties" >
                <value>
                    {"persistence-factory":
                        {"class":"com.foo.CustomHibernateSpringUtil",
                          "singleton" :"true", 
                          "method":"getSessionFactory"
                        },
                      "stateless":"false"
                    } 
                </value>
            </property>
        </bean>

        Comment


        • #5
          Thanks for the research and the great tip of the factory-method attribute on the HibernateSpringUtil bean definition...

          The following code snippet did the trick:
          Code:
          	<bean id="persistenceUtil" class="net.sf.gilead.core.hibernate.spring.HibernateSpringUtil" factory-method="getInstance">
          		<property name="sessionFactory" ref="sessionFactory" />
          	</bean>
          
          	<bean id="hibernate-object"
          		class="org.springframework.flex.core.ManageableComponentFactoryBean" depends-on="sessionFactory">
          		<constructor-arg value="net.sf.gilead.blazeds.adapter.PersistentAdapter" />
          		<property name="properties" >
          			<value>
          				{"persistence-factory":
          					{"class":"net.sf.gilead.core.hibernate.spring.HibernateSpringUtil",
          				 	 "singleton" :"true", 
          					 "method":"getSessionFactory"
          					},
          				 "stateless":"false"
          				} 
          			</value>
          		</property>
          	</bean>

          Comment


          • #6
            Just beware that the default getInstance method of HibernateSpringUtil returns an instance of HibernateUtil, so the special unwrapping of a potentially proxied SessionFactory will not happen. In that case, you may as well just use the base HibernateUtil.

            Btw, are you already set on using Gilead? I just noticed this interesting blog regarding Gilead vs. dpHibernate by one of our other community members:

            http://blog.cjtech.co.uk/index.php/2...-lazy-loading/

            Comment


            • #7
              Actually we're still in the beginning of our project, so we can still decide which way to go (Gilead/dpHibernate/...).

              Thanks for the tip (I already read the article you mentioned).
              But I'm not really expecting any 'automatic' lazy loading from the libraries itself or should I?

              I'll keep you posted...

              Comment


              • #8
                Handling of lazy loading with these sorts of frameworks (Flex, GWT, etc.) is a hard thing to get right. I haven't tried using either dpHibernate or Gilead in anger myself, so I really don't have an informed opinion there. I will say that the dpHibernate source looks a little cleaner to me, and I like the fact that it's targeted specifically at BlazeDS (whereas Gilead tries to be a more generic solution), but it's arguable how much that matters as long as whichever solution you choose works to satisfy your requirements.

                Comment


                • #9
                  > But I'm not really expecting any 'automatic' lazy loading from the libraries itself or should I?

                  Well if your not going to have your lazy collection automatically loading its real objects when needed (eg when you access the collection in Flex), then you will need to code a specific service method to retrieve the real objects in the collection and you'll need to create these methods for every collection you want to be lazy.

                  Gilead helps in the merging of the real objects to your proxy objects, but that's about it. Therefore, if you have a large model with lots of collections you want to be lazy, if you use Gilead, your going to have to write a load of code. If you use dpHibernate, you only need to get your hibernate mappings right (which you got to do anyway with Gilead too).

                  Comment


                  • #10
                    Hi all,

                    I am the Gilead author, and would like to give some precision on what has been written here.

                    First, Gilead was not developed to allow 'remote' lazy loading, first because I do believe that it will to very poor performances when misused (just imagine how N+1 select can ruin your application performances when done from Flex side !).
                    Instead, I wrote it according to the Hibernate 'detached state' model : once your entity is on Flex side, everything that has been loaded on server side is available, and lazy but not loaded properties are just replaced by null.
                    When your Flex code sends back the POJO to the server, the entity can be safely reused with Hibernate without any more manipulation.
                    It does not look to me a lot of code to write

                    So please, do not blame Gilead for not doing what it has not been made for.

                    Best Regards
                    Bruno

                    Comment


                    • #11
                      > It does not look to me a lot of code to write

                      Bruno I really think you are misunderstanding what developers are actually looking for when they mention BlazeDS, Hibernate and lazy-loading.

                      Imagine:

                      Code:
                      class Store
                      {
                          String name;
                          Array books;
                      }
                      
                      class Book
                      {
                          String title;
                          Array pages;
                      }
                      
                      class Page
                      {
                          String text;
                      }
                      
                      class WebService
                      {
                          Array getStores();
                      }
                      Now if these classes are in Hibernate, when you load a Store, you want the books array to only hold proxy objects so each of these proxy objects are basically empty, they have no pages or title. Hence a call to getStores lets say gives you 3 Store objects each with some proxy objects in their books arrays.
                      The client side code, if using automatic lazy-loading with something like dpHibernate does not need the developer to write any code to get the real book objects. They will automatically be loaded when the Store::books collection is accessed, eg store.books.getItemAt(0);
                      With Gilead however, you would need to create a new web service call to get the real book object(s).

                      If you have a big data model with lots of collections, this equates to much more code with Gilead.

                      Now I am not arguing that Gilead is no good or that it doesn't work or doesn't do anything etc etc, but it really does not do lazy-loading in the way expected or in any way the same or similar to dpHibernate.

                      I spent much time evaluating both Gilead and dpHibernate, simply because you have promoted it on every blog and forum post related to BlazeDS, Hibernate and lazy-loading.
                      But friend, it isnt anywhere near the same thing as dpHibernate, LCDS, GraniteDS when it comes to lazy-loading.
                      Last edited by jtgrassie; May 14th, 2009, 02:27 AM.

                      Comment


                      • #12
                        Ok, so now let's imagine the following code :
                        Code:
                        for(Post post : blog.getPosts())
                        {
                            for (Comment comment : post.getComments())
                            {
                                print(comment);
                            }
                        }
                        On server side, it generates N+1 SQL request (where N is the number of comments items), and it is known to produce very poor performances. It is a recognized bad practice.

                        With remote lazy loading from Flex, things are just worst : you will have N+1 server calls and N+1 database calls. This is just not acceptable, but dpHibernate and al allow it.
                        With Gilead, you will just have an empty, null "Post" collection, so you will know that you have to load them before use it. Just a different philosophy...

                        Finally, I never promoted Gilead to allow automatic lazy loading. Here is what's written on the home page of the project :
                        "Gilead stands for Generic Light Entity Adapter

                        It permits you to send Persistent entities (and especially the partially loaded ones) outside the JVM (GWT, Flex, Web-Services, ...) without pain.

                        No LazyInitialisationException. No DTO mapping. Just POJO and Domain Driven Design !"

                        Regards
                        Bruno

                        Comment


                        • #13
                          I'm one the developers of GraniteDS, and I completely agree with with Bruno that remote lazy loading can be very easily misused and should be avoided whenever possible. The most important thing with Gilead and GraniteDS is to be able to serialize detached entities, modify them from Flex and merge them back in the server persistence context.
                          Transparent lazy loading in GraniteDS or dpHibernate should be used only in a very limited set of use cases where it makes sense (mainly tree structures and master-details forms), and surely it is very handy in these cases.

                          Comment


                          • #14
                            @bruno
                            > Finally, I never promoted Gilead to allow automatic lazy loading.

                            Appologies. My mistake then. Just I always saw Gilead mentioned as an alternative to dpHibernate, pimento etc.

                            @wdrai
                            First up great work on GDS.

                            At no point do I disagree that transparent lazy loading should only be used where needed, but this is easily configured at server side via hibernate mappings/annotations. And of course, there is no problem creating specific code to deal with differing needs.
                            The model of the current job we are on, and hence have been looking into lazy loading, has a big ol tree structure that transparent lazy loading will help immensely with.

                            Comment


                            • #15
                              gilead vs. dphibernate

                              I'm choosing to use gilead personally. First of all, dphibernate doesn't seem to have been updated in the last 6 months.

                              Second of all, I avoid lazy loading of collections for performance wherever possible in all my Java code. I'd just be 10 times more careful to avoid it in Flex. The trouble I see is that it seems like it would be harder to diagnose inadvertent N+1 lazy loads in my Flex and I'd rather just avoid it and write explicit service calls which retrieve the sections of my domain model I need with a single joined SQL query in a java service.

                              They both help me avoid what I call the DTO problem: needing to create a second layer of DTOs to mask my hibernate objects and avoid BlazeDS automatically serializing my entire database. But the remote lazy loading of dpHibernate seems like something I won't want most of the time and I'm worried about the times where I don't want it but I inadvertently use it anyway.

                              Comment

                              Working...
                              X