views:

30

answers:

2

Hi all,

So, my problem is : All my project is (well ?) configured but I don't have lazy loading !

This a sample project I'm making to prepare the real project coming just after. In simple words, I have 3 tables : Category, Product, Client, and the association between the last two, Buy.

On the Flex side I have two simple datagrid, the first one contains the products, and the second one contains the clients associated with the selected product. On the server side a Spring-BlazeDS-Integration architecture and a service which retrieves all the products.

My config files : web.xml

enter code here

<web-app>
    <display-name>Spring BlazeDS Integration</display-name>
    <description>Spring BlazeDS Integration</description>

    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>/WEB-INF/classes/log4j.properties</param-value>
    </context-param>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/config/applicationContext.xml</param-value>
    </context-param>

    <filter>  
        <filter-name>openSessionInViewFilter</filter-name>  
        <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
        <init-param>
            <param-name>flushMode</param-name>
            <param-value>ALWAYS</param-value>
        </init-param>    
    </filter>

    <filter-mapping>  
        <filter-name>openSessionInViewFilter</filter-name>  
        <url-pattern>/messagebroker/*</url-pattern>
    </filter-mapping>

    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>Spring MVC Servlet Dispatcher</servlet-name>
        <display-name>Spring MVC Servlet Dispatcher</display-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/config/webApplicationContext.xml</param-value>
       </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet>
        <servlet-name>RDSDispatchServlet</servlet-name>
        <servlet-class>flex.rds.server.servlet.FrontEndServlet</servlet-class>
        <init-param>
            <param-name>messageBrokerId</param-name>
            <param-value>_messageBroker</param-value>
        </init-param>        
        <init-param>
            <param-name>useAppserverSecurity</param-name>
            <param-value>false</param-value>
        </init-param>        
        <load-on-startup>10</load-on-startup>
    </servlet>

    <servlet-mapping id="RDS_DISPATCH_MAPPING">
        <servlet-name>RDSDispatchServlet</servlet-name>
        <url-pattern>/CFIDE/main/ide.cfm</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>Spring MVC Servlet Dispatcher</servlet-name>
        <url-pattern>/messagebroker/*</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
    </welcome-file-list>
</web-app>

applicationContext.xml

<beans xmlns="..">
    <bean id="transactionProxy" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager" ref="txManager" />
        <property name="transactionAttributes">
            <props>
                <prop key="create*">PROPAGATION_REQUIRED</prop>
                <prop key="update*">PROPAGATION_REQUIRED</prop>
                <prop key="delete*">PROPAGATION_REQUIRED</prop>
                <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
            </props>
        </property>
    </bean>

    <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory">
            <ref local="sessionFactory"/>
        </property>
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="mappingResources">
            <list>
                <value>tuto/Product.hbm.xml</value>
                <value>tuto/Client.hbm.xml</value>
                <value>tuto/Category.hbm.xml</value>
                <value>tuto/Buy.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
        <property name="dataSource"><ref bean="dataSource"/></property>
    </bean>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/tuto" />
        <property name="username" value="root" />
    </bean>
</beans>

webApplicationContext.xml

<beans xmlns=".....">
    <bean id="hibernate-lazy-adapter" class="org.springframework.flex.core.ManageableComponentFactoryBean">
        <constructor-arg value="net.digitalprimates.persistence.hibernate.HibernateAdapter"/>
        <property name="properties">
            <value>
                {
                    "hibernate": {
                        "sessionFactory": {"class":"net.digitalprimates.persistence.hibernate.utils.SpringSessionUtil", "getCurrentSessionMethod":"getCurrentSession"
                        }, "loadMethod":"load"
                    }
                }
            </value>
        </property>
    </bean>

    <flex:message-broker>
        <flex:remoting-service default-adapter-id="hibernate-lazy-adapter" default-channels="my-amf" />
    </flex:message-broker>

    <bean id="productService" parent="transactionProxy">
        <property name="target">
            <bean class="tuto.ServiceProductImpl">
                <property name="productDAO"><ref bean="productDAO"/></property>
            </bean>
        </property>
        <flex:remoting-destination/>
    </bean>

    <bean id="productDAO" class="tuto.DAOProductHibernate" lazy-init="default">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
</beans>

product.hbm.xml

<hibernate-mapping package="tuto">
    <class name="Product" table="product">
        <id name="productId" type="long" column="product_id">
            <generator class="increment"/>
        </id>

        <property name="name" column="name" type="string" not-null="true" length="40"/>

        <many-to-one name="category" column="category_id" class="Category" not-null="true" lazy="false">
        </many-to-one>

        <set name="clients" table="buy" cascade="delete">
            <key column="product_id"/>
            <many-to-many column="client_id" class="Client"/>
        </set>
    </class>
</hibernate-mapping>

And here's the code in ProductDAO.java

public Collection<Product> findAll() {
    Session session = SessionFactoryUtils.getSession(getSessionFactory(), false);
    try {
        return session.createQuery("from Product").list();
    } catch (HibernateException e) {
        throw SessionFactoryUtils.convertHibernateAccessException(e);
    }
}

If you need more information to help, please ask, I just didn't want to post to much code in the first message :)

So as you can see I just retrieve the products from the database, but when I select a product in the datagrid, the client's datagrid is populated, so the Clients are loaded too ! Plus, I have a log trace and I can see there is more than one request on the Product table, there's also several on the Client table. In my opinion only one should be here ! No ?!

I'm waiting for your suggestion, thanks a lot !

Arnaud.

A: 

There is no mechanism of lazy loading in BlazeDS. If you need that you will have to write your own framework, or to use the data management from Livecycle DataServices. There is also an open source project aimed to do that, but I never played with it.

Another option is to use split your model and use remote methods in order to obtain the clients when the corresponding Product is selected.

Cornel Creanga
Thank you for the answer I forgot to say that I AM using dpHibernate :)I have no error in my logs but the lazy loading simply doesn't seems to work...All my database is loaded.
Arnaud
A: 

Problem solved !

Change this :

<flex:message-broker>
    <flex:remoting-service default-adapter-id="hibernate-lazy-adapter" default-channels="my-amf" />
</flex:message-broker>

to this :

<flex:message-broker>
</flex:message-broker>

And in all the beans, change this :

<flex:remoting-destination/>

to this :

<flex:remoting-destination service-adapter="hibernate-lazy-adapter" channels="my-amf"/>

Now it works :)

Arnaud