Announcement Announcement Module
Collapse
No announcement yet.
Spring + iBatis - out of memory!! Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring + iBatis - out of memory!!

    Hi, I´m having a problem with Spring + iBatis. The program loops forever and ends up with an out of memory error. here´s the code.


    applicationContext-jdbc.xml
    Code:
    <beans>
    	<!-- ========================= RESOURCE DEFINITIONS ========================= -->
    	<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    		<property name="location"><value>/bin/jdbc.properties</value></property>
    	</bean>
    	<!-- DataSource local que trajaba en cualquier entorno -->
    	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    		<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>
    	<!-- Mapping para la configuracion de iBatis -->
    	<bean id="sqlMap" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
    		<property name="configLocation"><value>/iBatis/sql-map-config.xml</value></property>
    	</bean>
    	<bean id="productDao" class="com.company.sample.persistence.jdbc.jdbc.ProductDaoImpl">
    		<property name="dataSource"><ref local="dataSource"/></property>
    		<property name="sqlMap"><ref local="sqlMap"/></property>
    	</bean>
    </beans>

    Product.xml
    Code:
    <sqlMap namespace="Products">
    
    	<cacheModel id="products-cache" type="MEMORY">
    		<flushInterval hours="24"/>
    		<flushOnExecute statement="insertProduct"/>
    		<flushOnExecute statement="updateProduct"/>
    		<flushOnExecute statement="deleteProduct"/>
    		<property name="reference-type" value="WEAK" />
    	</cacheModel>
    	
    	<typeAlias alias="product" type="com.company.sample.persistence.jdbc.dto.Product" />
    	<typeAlias alias="productPk" type="com.company.sample.persistence.jdbc.dto.ProductPk" />
    
    	<resultMap class="product" id="product-result" >
    		<result property="id" column="ID" />
    		<result property="description" column="DESCRIPTION" />
    	</resultMap>
    
    	<select id="getProduct" resultClass="product" parameterClass="productPk" resultMap="product-result" >
    		<!&#91;CDATA&#91;
    			select * from Referencia.PRODUCTS 
    			where ID = #id#
    		&#93;&#93;>
    	</select>
    
    	<update id="updateProduct" parameterClass="product" >
    		<!&#91;CDATA&#91;
    			update Referencia.PRODUCTS
    			set DESCRIPTION = #description#
    			where ID = #id#
    		&#93;&#93;>
    	</update>
    
    	<insert id="insertProduct" parameterClass="product" >
    		<!&#91;CDATA&#91;
    			insert into Referencia.PRODUCTS&#40;ID, DESCRIPTION&#41;
    			values&#40;#id#, #description#&#41;
    		&#93;&#93;>
    	</insert>	
    
    	<delete id="deleteProduct" parameterClass="productPk" >
    		<!&#91;CDATA&#91;
    			delete from Referencia.PRODUCTS
    			where ID = #id#
    		&#93;&#93;>
    	</delete>
    
    </sqlMap>
    Implementation of the ProductDao (ProductDao extendes SqlMapDao, SqlMapDao extends SqlMapDaoSupport)

    Code:
    public class ProductDaoImpl extends ProductDao &#123; 
       	protected static final Logger logger = Logger.getLogger&#40; ProductDaoImpl.class &#41;;
    			
        
        /* Inserts a new row in the PRODUCTS table.
         * @see com.company.framework.dao.core.Dao#insert&#40;java.lang.Object&#41;
         */
        public Object insert&#40;Object dto&#41; throws companyDataAccessException &#123;
        	Product product = &#40;Product&#41; dto;
    		if &#40;logger.isDebugEnabled&#40;&#41;&#41; &#123;
    			logger.debug&#40; "Executing " + SQL_INSERT + " with DTO&#58; " + product&#41;;
    		&#125;
    		this.getSqlMapTemplate&#40;&#41;.executeUpdate&#40;"insertProduct", new Object&#91;&#93; &#123;product.getId&#40;&#41;,product.getDescription&#40;&#41;&#125; &#41;;
    		return product.createPk&#40;&#41;;
        &#125;
        .....
        &#125;
    Test Code

    Code:
    ProductDao dao = ProductDaoFactory.create&#40;&#41;;
    Product product = new Product&#40;&#41;;
    product.setId&#40;new Integer&#40;1&#41;&#41;;
    product.setDescription&#40;"Producto el orto"&#41;;
    dao.insert&#40;product&#41;;
    System.out.println&#40;dao.findByPrimaryKey&#40;product.createPk&#40;&#41;&#41;&#41;;
    What´s wrong with these. I'm debugging the application but it seems to loop while initializing the beans.

  • #2
    I'm not clear at what point exactly it loops? When the Spring context is coming up? What environment do you run that test code in? Can you reproduce the endless loop without Spring configuration involved at all?

    Comment


    • #3
      I've found the error. I was loading thing more than once. I complitely forgot that Spring would load things for me and I was loading then by hand.
      Here's the solution the problem. I still need help with the test cases. How should I create and drop the tables??.. I would like to run the test as many times i want without falling into a DUPLICATE KEY exception or somethig like that..Thanks in advance.

      DBHelper - Helps me crete and drop the tables in the testcases so I can run over and over again, while
      making modifications to fit the desire logic.

      Code:
      public class DbHelper extends JdbcDaoSupport &#123;
      	public DbHelper&#40;&#41; &#123;
         	this.setDataSource&#40;ResourceManager.getDataSource&#40;&#41;&#41;;
      	&#125;
      &#125;
      The implementation of the interface ProductDao

      Code:
      public class ProductDaoImpl extends SqlMapClientDaoSupport implements ProductDao &#123; 
      	/** 
          * All finder methods in this class use this SELECT constant to build their queries
          */
          protected final String SQL_SELECT = "SELECT ID, DESCRIPTION FROM " + getTableName&#40;&#41; + "";
         /** 
          * SQL INSERT statement for this table
          */
          protected final String SQL_INSERT = "INSERT INTO " + getTableName&#40;&#41; + " &#40; ID, DESCRIPTION &#41; VALUES &#40; ?, ? &#41;";
         /**
          * Logger
          */
          protected static final Logger logger = Logger.getLogger&#40; ProductDaoImpl.class &#41;;
         
         /* Inserts a new row in the PRODUCTS table.
          * @see com.mycompany.framework.dao.core.Dao#insert&#40;java.lang.Object&#41;
          */
          public Object insert&#40;Object dto&#41; throws mycompanyDataAccessException &#123;
          	Product product = &#40;Product&#41; dto;
            if &#40;logger.isDebugEnabled&#40;&#41;&#41; &#123;
            	logger.debug&#40; "Executing " + SQL_INSERT + " with DTO&#58; " + product&#41;;
            &#125;
            this.getSqlMapClientTemplate&#40;&#41;.update&#40;"insertProduct", product &#41;;
            return product.createPk&#40;&#41;;
          &#125;
        
          /* Returns the rows from the PRODUCTS table that matches the specified primary-key value.
           * @see com.mycompany.framework.dao.core.Dao#findByPrimaryKey&#40;java.lang.Object&#41;
           */
          public Object findByPrimaryKey&#40;Object pk&#41; throws mycompanyDataAccessException &#123;
          	ProductPk productpk = &#40;ProductPk&#41; pk;
            if &#40;logger.isDebugEnabled&#40;&#41;&#41; &#123;
            	logger.debug&#40; "Executing " + SQL_SELECT + " with userPk&#58; " + productpk&#41;;
           	&#125;
            List ret = this.getSqlMapClientTemplate&#40;&#41;.queryForList&#40;"getProduct", pk &#41;;
            return &#40;Product&#41; &#40;ret.size&#40;&#41;==0 ? null &#58; ret.get&#40;0&#41;&#41;;
          &#125;
      
          /**
           * Method 'getTableName'
           * @return String
           */
           public String getTableName&#40;&#41; &#123;
              return "Referencia.PRODUCTS";
           &#125;
      &#125;
      Product.xml

      Code:
      <?xml version='1.0'?>
      
      <!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
              "http&#58;//www.ibatis.com/dtd/sql-map-2.dtd">
      
      <sqlMap namespace="Products">
      	<cacheModel id="products-cache" type="MEMORY">
         	<flushInterval hours="24"/>
            <flushOnExecute statement="insertProduct"/>
            <flushOnExecute statement="updateProduct"/>
            <flushOnExecute statement="deleteProduct"/>
            <property name="reference-type" value="WEAK" />
      	</cacheModel>
              
         <typeAlias alias="product" type="com.mycompany.sample.persistence.jdbc.dto.Product" />
         <typeAlias alias="productPk" type="com.mycompany.sample.persistence.jdbc.dto.ProductPk" />
      
         <resultMap class="product" id="product-result" >
         	<result property="id" column="ID" />
            <result property="description" column="DESCRIPTION" />
      	</resultMap>
      
      	<select id="getProduct" resultClass="product" parameterClass="productPk" resultMap="product-result" >
         	<!&#91;CDATA&#91;
            	select * from Referencia.PRODUCTS 
               where ID = #id#
             &#93;&#93;>
      	</select>
      
         <update id="updateProduct" parameterClass="product" >
         	<!&#91;CDATA&#91;
               update Referencia.PRODUCTS
               set DESCRIPTION = #description#
               where ID = #id#
             &#93;&#93;>
      	</update>
      
         <insert id="insertProduct" parameterClass="product" >
         	<!&#91;CDATA&#91;
            	insert into Referencia.PRODUCTS&#40;ID, DESCRIPTION&#41;
               values&#40;#id#, #description#&#41;
             &#93;&#93;>
      	</insert>       
      
         <delete id="deleteProduct" parameterClass="productPk" >
         	<!&#91;CDATA&#91;
               delete from Referencia.PRODUCTS
               where ID = #id#
             &#93;&#93;>
      	</delete>
      </sqlMap>
      Test Case

      Code:
      public class ProductsDaoImpTest extends TestCase &#123;
      	public static void main&#40;String&#91;&#93; args&#41; &#123;
         	junit.textui.TestRunner.run&#40;ProductsDaoImpTest.class&#41;;
         &#125;
         /*
          * @see TestCase#setUp&#40;&#41;
          */
          protected void setUp&#40;&#41; throws Exception &#123;
         	  DbHelper dbh = new DbHelper&#40;&#41;;
              dbh.getJdbcTemplate&#40;&#41;.execute&#40;"CREATE TABLE PRODUCTS&#40;ID INTEGER NOT NULL PRIMARY KEY,DESCRIPTION VARCHAR&#40;250&#41; NOT NULL&#41;"&#41;;
              super.setUp&#40;&#41;;
          &#125;
      
          /*
           * @see TestCase#tearDown&#40;&#41;
           */
          protected void tearDown&#40;&#41; throws Exception &#123;
              DbHelper dbh = new DbHelper&#40;&#41;;
              dbh.getJdbcTemplate&#40;&#41;.execute&#40;"DROP TABLE PRODUCTS"&#41;;
              super.tearDown&#40;&#41;;
          &#125;
         
          /*
           * Class under test for Object findByPrimaryKey&#40;Object&#41;
           */
          public void testFindByPrimaryKeyObject&#40;&#41; &#123;
              // ProductDao dao = ProductDaoFactory.create&#40;&#41;;
              Product product = new Product&#40;&#41;;
              product.setId&#40;new Integer&#40;1&#41;&#41;;
              product.setDescription&#40;"Producto el orto"&#41;;
              ApplicationContext context = new FileSystemXmlApplicationContext&#40;"applicationContext-jdbc.xml"&#41;;
              ProductDaoImpl dao = &#40;ProductDaoImpl&#41; context.getBean&#40;"productDao"&#41;; 
              dao.insert&#40;product&#41;;
              System.out.println&#40;dao.findByPrimaryKey&#40;product.createPk&#40;&#41;&#41;&#41;;
          &#125;
      &#125;
      iBatis Configuration

      Code:
      <sqlMapConfig>
      
        <properties resource="jdbc.properties"/>
      
        <settings
          cacheModelsEnabled="true"
          enhancementEnabled="true"
          maxSessions="64"
          maxTransactions="8"
          maxRequests="128"/>
      
        <!--transactionManager type="JDBC">
          <dataSource type="SIMPLE">
            <property value="$&#123;jdbc.driverClassName&#125;" name="JDBC.Driver"/>
            <property value="$&#123;jdbc.url&#125;" name="JDBC.ConnectionURL"/>
            <property value="$&#123;jdbc.username&#125;" name="JDBC.Username"/>
            <property value="$&#123;jdbc.password&#125;" name="JDBC.Password"/>
            <property value="15" name="Pool.MaximumActiveConnections"/>
            <property value="15" name="Pool.MaximumIdleConnections"/>
            <property value="1000" name="Pool.MaximumWait"/>
          </dataSource>
        </transactionManager-->
         
        <sqlMap resource="com/mycompany/sample/persistence/jdbc/scripts/iBatis/Products.xml"/>
        
      </sqlMapConfig>
      Spring configuration

      Code:
      <beans>
              <!-- ========================= RESOURCE DEFINITIONS ========================= -->
              <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
                      <property name="location"><value>/bin/jdbc.properties</value></property>
              </bean>
              <!-- DataSource local que trajaba en cualquier entorno -->
              <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                      <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>
              <!-- Mapping para la configuracion de iBatis -->
              <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
                      <property name="configLocation"><value>sql-map-config.xml</value></property>
              </bean>
                
              <bean id="productDao" class="com.mycompany.sample.persistence.jdbc.jdbc.ProductDaoImpl">
                      <property name="dataSource"><ref local="dataSource"/></property>
                      <property name="sqlMapClient"><ref local="sqlMapClient"/></property>
              </bean>
      </beans>

      Comment


      • #4
        I still need help with the test cases. How should I create and drop the tables??..
        Look at the org.springframework.test package, shipped in spring-mock.jar. I've updated the PetClinic tests to use it (just post 1.1.4, unfortunately), and added a chapter in the Reference Manual (which also may not be published yet, but should be available soon).

        This is designed to run each test in its own transaction, rolling back by default. I've found it a very convenient technique for testing involving a database, and it's produced a big productivity benefit in several projects.

        Comment

        Working...
        X