Announcement Announcement Module
Collapse
No announcement yet.
Spring + iBATIS + lazy-loading: NullPointerException Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring + iBATIS + lazy-loading: NullPointerException

    Hello,
    i'm using Spring 1.1.3 and iBATIS SQLMaps 2.0.9 and having trouble trying to use lazy-loading.
    Here are the source code and the configuration files i used:

    The beans:
    Code:
    ---------------- Category.java -------------------
    package test.bo;
    
    import java.util.List;
    
    public class Category
    {
    	private int id;
    	private String Name; 
    	
    	public int getId()
    	{
    		return id;
    	}
    
    	public String getName()
    	{
    		return Name;
    	}
    
    	public void setId(int i)
    	{
    		id = i;
    	}
    
    	public void setName(String string)
    	{
    		Name = string;
    	}
    
    }
    -------------- Product.java --------------
    package test.bo;
    
    
    public class Product
    {
    	private int id;
    	private String Name;
    	private int catId;
    	private Category category;
    	
    	public int getCatId()
    	{
    		return catId;
    	}
    
    	public int getId()
    	{
    		return id;
    	}
    
    	public String getName()
    	{
    		return Name;
    	}
    
    	public void setCatId(int i)
    	{
    		catId = i;
    	}
    
    	public void setId(int i)
    	{
    		id = i;
    	}
    
    	public void setName(String string)
    	{
    		Name = string;
    	}
    
    	public Category getCategory()
    	{
    		return category;
    	}
    
    	public void setCategory(Category category)
    	{
    		this.category = category;
    	}
    }
    The DAO
    Code:
    package test.simple;
    
    import java.util.List;
    
    import org.springframework.dao.DataAccessException;
    import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
    
    
    public class SimpleSqlMapProductDAO extends SqlMapClientDaoSupport
    {
    	
    	public List getAllProducts() throws DataAccessException
    	{
    		return getSqlMapClientTemplate().queryForList("selectAllProducts", null);
    	}
    
    }
    The configuration files
    Code:
    ------- spring-config.xml----------
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "file&#58;///C&#58;/wsad/SDDC/workspace/SPRING_iBATIS_RESOURCES/dtd/spring-beans.dtd">
    <beans>
    
    	<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
    		<property name="configLocation">
    			<value>sqlmap-config.xml</value>
    		</property>
    	</bean>
    
    	<!-- property placeholder post-processor -->
    	<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    		<property name="location">
    			<value>jdbc.properties</value>
    		</property>
    	</bean>
    
    	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    		<property name="driverClassName">
    			<value>$&#123;jdbc.driverClassName&#125;</value>
    		</property>
    		<property name="url">
    			<value>$&#123;jdbc.url&#125;</value>
    		</property>
    		<property name="username">
    			<value>$&#123;jdbc.username&#125;</value>
    		</property>
    		<property name="password">
    			<value>$&#123;jdbc.password&#125;</value>
    		</property>
    		
    	</bean>
    
    	<bean id="simpleProductDAO" class="test.simple.SimpleSqlMapProductDAO">
    		<property name="dataSource">
    			<ref local="dataSource" />
    		</property>
    		<property name="sqlMapClient">
    			<ref local="sqlMapClient" />
    		</property>
    	</bean>
    	
    </beans>
    Code:
    -------- sqlmap-config.xml --------
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
    "C&#58;/wsad/SDDC/workspace/SPRING_iBATIS_RESOURCES/dtd/sql-map-config-2.dtd">
    <sqlMapConfig>
    	<properties resource="jdbc.properties" />
    
    	<settings cacheModelsEnabled="true" 
    			enhancementEnabled="false"
    			lazyLoadingEnabled="false"
    			maxRequests="32"
    			maxSessions="10"
    			maxTransactions="5"
    			useStatementNamespaces="false" />
    
    	<sqlMap resource="sqlmap-product.xml" />
    	<sqlMap resource="sqlmap-category.xml" />
    
    
    </sqlMapConfig>
    Code:
    -------- sqlmap-category.xml -------
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE sqlMap
    PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
    "C&#58;/wsad/SDDC/workspace/SPRING_iBATIS_RESOURCES/dtd/sql-map-2.dtd">
    <sqlMap namespace="Category">
    
    	<typeAlias alias="CategoryClass" type="test.bo.Category"/>
    
    	<resultMap id="category" class="CategoryClass">
    		<result property="id" column="ID"/>
    		<result property="name" column="NAME"/>	
    	</resultMap>
    		
    	<select id="selectCategoryById" resultMap="category" parameterClass="int">
    		SELECT *
    		FROM $&#123;jdbc.schema&#125;.CATEGORY
    		WHERE ID = #value#
    	</select>
    
    </sqlMap>
    Code:
    -------sqlmap-product.xml ---------
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE sqlMap
    PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
    "C&#58;/wsad/SDDC/workspace/SPRING_iBATIS_RESOURCES/dtd/sql-map-2.dtd">
    <sqlMap namespace="Product">
    	
    	<typeAlias alias="ProductClass" type="test.bo.Product"/>
    	
    	<resultMap id="product" class="ProductClass">
    		<result property="id" column="ID"/> 
    		<result property="name" column ="NAME"/>
    		<result property="catId" column="CAT_ID"/>
    		<result property="category" column="CAT_ID" select="selectCategoryById"/>
    	</resultMap>
    
    	
    	<select id="selectAllProducts" resultMap="product">
    		SELECT *
    		FROM $&#123;jdbc.schema&#125;.PRODUCT
    		ORDER BY ID
    	</select>
    	
    </sqlMap>
    The main program
    Code:
    package test.simple;
    
    import java.util.Iterator;
    
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import test.bo.Product;
    
    public class SimpleTestProduct
    &#123;
    
    	public static void main&#40;String&#91;&#93; args&#41; throws Exception
    	&#123;
    		ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext&#40;"spring-config.xml"&#41;;
    		SimpleSqlMapProductDAO dao = &#40;SimpleSqlMapProductDAO&#41; ac.getBean&#40;"simpleProductDAO"&#41;;
    
    		// SELECT * 
    		Iterator products = dao.getAllProducts&#40;&#41;.iterator&#40;&#41;;
    		while &#40;products.hasNext&#40;&#41;&#41;
    		&#123;
    			Product product = &#40;Product&#41; products.next&#40;&#41;;
    			System.out.println&#40;"Product n" + product.getId&#40;&#41; + " &#58; " + product.getName&#40;&#41; + "&#40;category=" + product.getCategory&#40;&#41;.getName&#40;&#41; + "&#41;"&#41;;
    			System.out.flush&#40;&#41;;
    		&#125;
    
    	&#125;
    &#125;
    -----------------------------------
    When i run the main program, everything works fine and i get my list of products with their associated categories.

    As soon as i turn lazyLoadingEnabled and enhancementEnabled to true in sqlmap-config.xml, the execution of the main program gives:
    Code:
    DEBUG &#91;main&#93; - Opening JDBC connection
    DEBUG &#91;main&#93; - &#123;conn-100000&#125; Connection
    DEBUG &#91;main&#93; - &#123;pstm-100001&#125; PreparedStatement&#58;    SELECT *   FROM EVAL.PRODUCT   ORDER BY ID  
    DEBUG &#91;main&#93; - &#123;pstm-100001&#125; Parameters&#58; &#91;&#93;
    DEBUG &#91;main&#93; - &#123;pstm-100001&#125; Types&#58; &#91;&#93;
    DEBUG &#91;main&#93; - &#123;rset-100002&#125; ResultSet
    DEBUG &#91;main&#93; - &#123;rset-100002&#125; Header&#58; &#91;ID, NAME, CAT_ID, CAT_ID&#93;
    DEBUG &#91;main&#93; - &#123;rset-100002&#125; Result&#58; &#91;1, test40 The Wire, 1, 1&#93;
    DEBUG &#91;main&#93; - &#123;rset-100002&#125; Result&#58; &#91;2, The Shield, 1, 1&#93;
    DEBUG &#91;main&#93; - &#123;rset-100002&#125; Result&#58; &#91;3, CSI, 1, 1&#93;
    DEBUG &#91;main&#93; - &#123;rset-100002&#125; Result&#58; &#91;4, Six Feet Under, 2, 2&#93;
    DEBUG &#91;main&#93; - &#123;rset-100002&#125; Result&#58; &#91;5, Nip/Tuck, 2, 2&#93;
    DEBUG &#91;main&#93; - &#123;rset-100002&#125; Result&#58; &#91;6, Friends, 3, 3&#93;
    DEBUG &#91;main&#93; - &#123;rset-100002&#125; Result&#58; &#91;7, Lost, 2, 2&#93;
    DEBUG &#91;main&#93; - &#123;rset-100002&#125; Result&#58; &#91;9, Desperate Housewire, 2, 2&#93;
    DEBUG &#91;main&#93; - &#123;rset-100002&#125; Result&#58; &#91;18, DUPLICATE, 3, 3&#93;
    DEBUG &#91;main&#93; - Closing JDBC connection
    Exception in thread "main" java.lang.NullPointerException
    	at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.endTransaction&#40;SqlMapExecutorDelegate.java&#58;776&#41;
    	at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.endTransaction&#40;SqlMapSessionImpl.java&#58;141&#41;
    	at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.endTransaction&#40;SqlMapClientImpl.java&#58;114&#41;
    	at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.autoEndTransaction&#40;SqlMapExecutorDelegate.java&#58;860&#41;
    	at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject&#40;SqlMapExecutorDelegate.java&#58;568&#41;
    	at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject&#40;SqlMapExecutorDelegate.java&#58;536&#41;
    	at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForObject&#40;SqlMapSessionImpl.java&#58;97&#41;
    	at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForObject&#40;SqlMapClientImpl.java&#58;69&#41;
    	at com.ibatis.sqlmap.engine.mapping.result.loader.ResultLoader.getResult&#40;ResultLoader.java&#58;77&#41;
    	at com.ibatis.sqlmap.engine.mapping.result.loader.EnhancedLazyResultLoader$EnhancedLazyResultLoaderImpl.loadObject&#40;EnhancedLazyResultLoader.java&#58;130&#41;
    	at com.ibatis.sqlmap.engine.mapping.result.loader.EnhancedLazyResultLoader$EnhancedLazyResultLoaderImpl.invoke&#40;EnhancedLazyResultLoader.java&#58;113&#41;
    	at test.bo.Category$$EnhancerByCGLIB$$ebd53ac1.getName&#40;<generated>&#41;
    	at test.simple.SimpleTestProduct.main&#40;SimpleTestProduct.java&#58;22&#41;
    It sounds like the first mapped statement "selectAllProducts" is well executed but then a failure occurs while trying to "lazy-load" categories.
    Can someone look at this anf help me pinpointing what wrong here ?
    Thanx in advance,
    Pascal.

  • #2
    Well the line you pointed out is the following:

    Code:
    txManager.end&#40;session&#41;;
    So I'd assume it has something to do with the way you've set up your transactions (txManager is the iBatis transaction manager). When you're using iBatis with Spring, Spring automatically sets iBatis up so that it is using an 'external' transaction manager, i.e. transactions are managed by Spring itself. And when you use lazy loading, the code calling which causes something to be loaded lazily needs to be executed within the same transaction as the initial database call (I think - I could be wrong on that point).

    In my setup (which does use lazy loading), I don't have any of the maxRequests, maxSessions or maxTransactions attributes in my sqlmap. Nor do I have the JDBC properties. Rather, all transaction handling is handled by Spring.

    Geoff

    Comment


    • #3
      I gave it another try after removing the maxRequests, maxSessions and maxTransactions settings properties but it failed again with the same error.
      Geoff, could you please show me what your configuration files look like, with lazy-loading on ?

      Comment


      • #4
        Sure, I can post some snippets. My sql-map-config.xml file looks like this:

        Code:
        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE sqlMapConfig
        	PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
        	"http&#58;//www.ibatis.com/dtd/sql-map-config-2.dtd">
        	
        <sqlMapConfig>
        
        	<!-- Global settings -->
        	<settings 
        		enhancementEnabled="true"
        		lazyLoadingEnabled="true" 
        		useStatementNamespaces="true" />
        		
        	<!-- Type aliases -->
        	...
        
        	<!-- Maps -->
        	... 
        
        </sqlMapConfig>
        Then my application context includes this:

        Code:
        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE beans PUBLIC 
        	"-//SPRING//DTD BEAN//EN" 
        	"http&#58;//www.springframework.org/dtd/spring-beans.dtd">
        	
        <beans>
        
        	<!-- Retrieves a data source from JNDI -->
        	<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        		<property name="jndiName"><value>$&#123;db.jndiname&#125;</value></property>
        	</bean>
        
        	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        		<property name="dataSource"><ref local="dataSource"/></property>
        	</bean>
        	
        	<bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
        		<property name="transactionManager"><ref bean="transactionManager"/></property>
        		<property name="transactionAttributes">
        			<props>
        				<prop key="insert*">PROPAGATION_REQUIRED</prop>
        				<prop key="update*">PROPAGATION_REQUIRED</prop>
        				<prop key="delete*">PROPAGATION_REQUIRED</prop>
        				<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
        			</props>
        		</property>
        	</bean>
        	
        	...
        
        </beans>
        Then any beans which include code which invokes the lazy-loading need to be wrapped by the transaction proxy, eg:

        Code:
        	<bean id="productService" parent="baseTransactionProxy">
        		<property name="target">
        			<bean class="example.ProductServiceImpl">
        				<property name="productDao"><ref local="productDao"/></property>
        			</bean>
        		</property>
        	</bean>
        Obviously, I've left out some other necessary items (e.g. the sql maps, the data access object beans, etc), but you should be able to piece together the rest.

        Hope this is of some assistance.

        Geoff

        Comment


        • #5
          I tried to add some transactional wrapping around my SimpleProductDAO.getAllProducts() method but it still fails
          I turned my spring-config.xml content to:
          Code:
          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "file&#58;///C&#58;/wsad/SDDC/workspace/SPRING_iBATIS_RESOURCES/dtd/spring-beans.dtd">
          <beans>
          
          	<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
          		<property name="configLocation">
          			<value>sqlmap-config.xml</value>
          		</property>
          	</bean>
          
          	<!-- property placeholder post-processor -->
          	<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
          		<property name="location">
          			<value>jdbc.properties</value>
          		</property>
          	</bean>
          
          	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
          		<property name="driverClassName">
          			<value>$&#123;jdbc.driverClassName&#125;</value>
          		</property>
          		<property name="url">
          			<value>$&#123;jdbc.url&#125;</value>
          		</property>
          		<property name="username">
          			<value>$&#123;jdbc.username&#125;</value>
          		</property>
          		<property name="password">
          			<value>$&#123;jdbc.password&#125;</value>
          		</property>
          		
          	</bean>
          
          	<bean id="simpleProductDAOTarget" class="test.simple.SimpleSqlMapProductDAO">
          		<property name="dataSource">
          			<ref local="dataSource" />
          		</property>
          		<property name="sqlMapClient">
          			<ref local="sqlMapClient" />
          		</property>
          	</bean>
          	
          	<!-- transaction manager -->
          	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
          		<property name="dataSource">
          			<ref local="dataSource" />
          		</property>
          	</bean>
          
          	<bean id="simpleProductDAO" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
          		<property name="proxyTargetClass">
          			<value>true</value>
          		</property>
          		<property name="transactionManager">
          			<ref bean="transactionManager" />
          		</property>
          		<property name="target">
          			<ref bean="simpleProductDAOTarget" />
          		</property>
          		<property name="transactionAttributes">
          			<props>
          				<prop key="get*">PROPAGATION_REQUIRED, readOnly</prop>
          			</props>
          		</property>
          	</bean>
          </beans>
          But the execution of the main program gives:
          Code:
          DEBUG &#91;main&#93; - Using transaction object &#91;org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@189559e4&#93;
          DEBUG &#91;main&#93; - Creating new transaction
          DEBUG &#91;main&#93; - Opening new connection for JDBC transaction
          DEBUG &#91;main&#93; - Opening JDBC connection
          DEBUG &#91;main&#93; - Setting JDBC connection &#91;org.apache.commons.dbcp.PoolableConnection@2ffc59e4&#93; read-only
          DEBUG &#91;main&#93; - Switching JDBC connection &#91;org.apache.commons.dbcp.PoolableConnection@2ffc59e4&#93; to manual commit
          DEBUG &#91;main&#93; - Bound value &#91;org.springframework.jdbc.datasource.ConnectionHolder@1f0719e4&#93; for key &#91;org.apache.commons.dbcp.BasicDataSource@5e619e7&#93; to thread &#91;main&#93;
          DEBUG &#91;main&#93; - Initializing transaction synchronization
          DEBUG &#91;main&#93; - Retrieved value &#91;org.springframework.jdbc.datasource.ConnectionHolder@1f0719e4&#93; for key &#91;org.apache.commons.dbcp.BasicDataSource@5e619e7&#93; bound to thread &#91;main&#93;
          DEBUG &#91;main&#93; - &#123;conn-100000&#125; Connection
          DEBUG &#91;main&#93; - &#123;pstm-100001&#125; PreparedStatement&#58;    SELECT *   FROM EVAL.PRODUCT   ORDER BY PRD_ID  
          DEBUG &#91;main&#93; - &#123;pstm-100001&#125; Parameters&#58; &#91;&#93;
          DEBUG &#91;main&#93; - &#123;pstm-100001&#125; Types&#58; &#91;&#93;
          DEBUG &#91;main&#93; - &#123;rset-100002&#125; ResultSet
          DEBUG &#91;main&#93; - &#123;rset-100002&#125; Header&#58; &#91;PRD_ID, PRD_NAME, PRD_CATID, PRD_ID&#93;
          DEBUG &#91;main&#93; - &#123;rset-100002&#125; Result&#58; &#91;1, The Wire, 1, 1&#93;
          DEBUG &#91;main&#93; - &#123;rset-100002&#125; Result&#58; &#91;2, The Shield, 1, 2&#93;
          DEBUG &#91;main&#93; - &#123;rset-100002&#125; Result&#58; &#91;3, CSI, 1, 3&#93;
          DEBUG &#91;main&#93; - &#123;rset-100002&#125; Result&#58; &#91;4, Six Feet Under, 2, 4&#93;
          DEBUG &#91;main&#93; - &#123;rset-100002&#125; Result&#58; &#91;5, Nip/Tuck, 2, 5&#93;
          DEBUG &#91;main&#93; - &#123;rset-100002&#125; Result&#58; &#91;6, Friends, 3, 6&#93;
          DEBUG &#91;main&#93; - &#123;rset-100002&#125; Result&#58; &#91;7, Lost, 2, 7&#93;
          DEBUG &#91;main&#93; - &#123;rset-100002&#125; Result&#58; &#91;9, Desperate Housewire, 2, 9&#93;
          DEBUG &#91;main&#93; - Retrieved value &#91;org.springframework.jdbc.datasource.ConnectionHolder@1f0719e4&#93; for key &#91;org.apache.commons.dbcp.BasicDataSource@5e619e7&#93; bound to thread &#91;main&#93;
          DEBUG &#91;main&#93; - Invoking commit for transaction on method 'getAllProducts' in class &#91;test.simple.SimpleSqlMapProductDAO&#93;
          DEBUG &#91;main&#93; - Triggering beforeCommit synchronization
          DEBUG &#91;main&#93; - Triggering beforeCompletion synchronization
          DEBUG &#91;main&#93; - Initiating transaction commit
          DEBUG &#91;main&#93; - Committing JDBC transaction on connection &#91;org.apache.commons.dbcp.PoolableConnection@2ffc59e4&#93;
          DEBUG &#91;main&#93; - Triggering afterCompletion synchronization
          DEBUG &#91;main&#93; - Clearing transaction synchronization
          DEBUG &#91;main&#93; - Removed value &#91;org.springframework.jdbc.datasource.ConnectionHolder@1f0719e4&#93; for key &#91;org.apache.commons.dbcp.BasicDataSource@5e619e7&#93; from thread &#91;main&#93;
          DEBUG &#91;main&#93; - Resetting read-only flag of connection &#91;org.apache.commons.dbcp.PoolableConnection@2ffc59e4&#93;
          DEBUG &#91;main&#93; - Closing JDBC connection &#91;org.apache.commons.dbcp.PoolableConnection@2ffc59e4&#93; after transaction
          DEBUG &#91;main&#93; - Closing JDBC connection
          Exception in thread "main" java.lang.NullPointerException
          	at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.endTransaction&#40;SqlMapExecutorDelegate.java&#58;776&#41;
          	at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.endTransaction&#40;SqlMapSessionImpl.java&#58;141&#41;
          	at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.endTransaction&#40;SqlMapClientImpl.java&#58;114&#41;
          	at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.autoEndTransaction&#40;SqlMapExecutorDelegate.java&#58;860&#41;
          	at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject&#40;SqlMapExecutorDelegate.java&#58;568&#41;
          	at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject&#40;SqlMapExecutorDelegate.java&#58;536&#41;
          	at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForObject&#40;SqlMapSessionImpl.java&#58;97&#41;
          	at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForObject&#40;SqlMapClientImpl.java&#58;69&#41;
          	at com.ibatis.sqlmap.engine.mapping.result.loader.ResultLoader.getResult&#40;ResultLoader.java&#58;77&#41;
          	at com.ibatis.sqlmap.engine.mapping.result.loader.EnhancedLazyResultLoader$EnhancedLazyResultLoaderImpl.loadObject&#40;EnhancedLazyResultLoader.java&#58;130&#41;
          	at com.ibatis.sqlmap.engine.mapping.result.loader.EnhancedLazyResultLoader$EnhancedLazyResultLoaderImpl.invoke&#40;EnhancedLazyResultLoader.java&#58;113&#41;
          	at test.bo.Category$$EnhancerByCGLIB$$ebd53ac1.getName&#40;<generated>&#41;
          	at test.simple.SimpleTestProduct.main&#40;SimpleTestProduct.java&#58;22&#41;
          We can see some transactional wrapping is on but does not solve the problem.
          I must admit i'm pretty lost here since i know you've been able to implement lazy-loading with Spring/iBATIS without trouble. My configuration sounds like yours but obviously something is wrong on my side and i just can find what is it... :evil:[/code][/i]

          Comment


          • #6
            Ah, I think I see why. Your external transaction manager is never actually being configured because your SqlMapClientFactoryBean isn't being passed a data source. In your applicationConfig.xml, simply configure your SqlMapClientFactoryBean to also have a reference to your dataSource bean.

            Regards,
            Geoff

            Comment


            • #7
              YEEEESSS, you were right.
              I added the datasource definition to the factory's and it works now perfectly. Many Thanks!

              Comment

              Working...
              X