I will interpret this as "You don't need interfaces for the proxying in lazy
loading to work" and send some more info. Attached are a lot of files... :)

On 10/2/07, Niels Beekman <[EMAIL PROTECTED]> wrote:
>
>  Please post relevant SQLMap and 
> net.bioclipse.structuredb.domain.Librarycode. It's difficult to see what's 
> going on without them.
>
>
>
> Niels
>  ------------------------------
>
> *From:* Jonathan Alvarsson [mailto:[EMAIL PROTECTED]
> *Sent:* dinsdag 2 oktober 2007 11:02
> *To:* [email protected]
> *Subject:* Lazy loading -- IllegalArgumentException: argument type
> mismatch
>
>
>
> I have tried to activate the lazy loading in iBatis. From working
> perfectly without lazy loading I turn into lot's of exceptions like this
> one:
>
> org.springframework.jdbc.UncategorizedSQLException: SqlMapClient
> operation; uncategorized SQLException for SQL []; SQL state [null]; error
> code [0];
> --- The error occurred in sqlMap.xml.
> --- The error occurred while applying a result map.
> --- Check the Library.
> --- The error happened while setting a property on the result object.
> --- Cause: java.lang.RuntimeException: Error setting property
> 'setStructures' of '[EMAIL PROTECTED] '.
> Cause: java.lang.IllegalArgumentException: argument type mismatch; nested
> exception is com.ibatis.common.jdbc.exception.NestedSQLException:
> --- The error occurred in sqlMap.xml.
> --- The error occurred while applying a result map.
> --- Check the Library.
> --- The error happened while setting a property on the result object.
> --- Cause: java.lang.RuntimeException: Error setting property
> 'setStructures' of '[EMAIL PROTECTED] '.
> Cause: java.lang.IllegalArgumentException: argument type mismatch
> Caused by: com.ibatis.common.jdbc.exception.NestedSQLException:
> --- The error occurred in sqlMap.xml.
> --- The error occurred while applying a result map.
> --- Check the Library.
> --- The error happened while setting a property on the result object.
> --- Cause: java.lang.RuntimeException: Error setting property
> 'setStructures' of '[EMAIL PROTECTED] '.
> Cause: java.lang.IllegalArgumentException: argument type mismatch
>     at
> com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback
> (GeneralStatement.java:188)
>     at
> com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryForObject(
> GeneralStatement.java:104)
>     at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject
> (SqlMapExecutorDelegate.java:566)
>     at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject
> (SqlMapExecutorDelegate.java :541)
>     at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForObject(
> SqlMapSessionImpl.java:106)
>     at
> org.springframework.orm.ibatis.SqlMapClientTemplate$1.doInSqlMapClient(
> SqlMapClientTemplate.java:243)
>     at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(
> SqlMapClientTemplate.java:193)
>     at org.springframework.orm.ibatis.SqlMapClientTemplate.queryForObject(
> SqlMapClientTemplate.java:241)
>     at net.bioclipse.structuredb.persistency.dao.GenericDao.getById (
> GenericDao.java:55)
>     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>     at sun.reflect.NativeMethodAccessorImpl.invoke(
> NativeMethodAccessorImpl.java:39)
>     at sun.reflect.DelegatingMethodAccessorImpl.invoke (
> DelegatingMethodAccessorImpl.java:25)
>     at java.lang.reflect.Method.invoke(Method.java:597)
>     at
> org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(
> AopUtils.java:296)
>     at
> org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(
> ReflectiveMethodInvocation.java:177)
>     at
> org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(
> ReflectiveMethodInvocation.java:144)
>     at
> net.bioclipse.structuredb.persistency.dao.FetchIntroductionInterceptor.invoke(
> FetchIntroductionInterceptor.java:36)
>     at
> org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(
> ReflectiveMethodInvocation.java:166)
>     at org.springframework.aop.framework.JdkDynamicAopProxy.invoke (
> JdkDynamicAopProxy.java:204)
>     at $Proxy6.getById(Unknown Source)
>     at net.bioclipse.structuredb.persistency.dao.GenericDaoTest.testUpdate
> (GenericDaoTest.java:122)
>     at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
>     at sun.reflect.NativeMethodAccessorImpl.invoke(
> NativeMethodAccessorImpl.java:39)
>     at sun.reflect.DelegatingMethodAccessorImpl.invoke(
> DelegatingMethodAccessorImpl.java:25)
>     at java.lang.reflect.Method.invoke (Method.java:597)
>     at junit.framework.TestCase.runTest(TestCase.java:168)
>     at junit.framework.TestCase.runBare(TestCase.java:134)
>     at org.springframework.test.ConditionalTestCase.runBare(
> ConditionalTestCase.java :69)
>     at
> org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.access$001
> (AbstractAnnotationAwareTransactionalTests.java:47)
>     at
> org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests$1.run(
> AbstractAnnotationAwareTransactionalTests.java:115)
>     at
> org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runTest
> (AbstractAnnotationAwareTransactionalTests.java:180)
>     at
> org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runTestTimed(
> AbstractAnnotationAwareTransactionalTests.java:153)
>     at
> org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runBare
> (AbstractAnnotationAwareTransactionalTests.java:111)
>     at junit.framework.TestResult$1.protect (TestResult.java:110)
>     at junit.framework.TestResult.runProtected(TestResult.java:128)
>     at junit.framework.TestResult.run(TestResult.java:113)
>     at junit.framework.TestCase.run(TestCase.java:124)
>     at junit.framework.TestSuite.runTest(TestSuite.java:232)
>     at junit.framework.TestSuite.run(TestSuite.java:227)
>     at org.junit.internal.runners.OldTestClassRunner.run(
> OldTestClassRunner.java:76)
>     at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run (
> JUnit4TestReference.java:38)
>     at org.eclipse.jdt.internal.junit.runner.TestExecution.run(
> TestExecution.java:38)
>     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(
> RemoteTestRunner.java:460)
>     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(
> RemoteTestRunner.java:673)
>     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(
> RemoteTestRunner.java:386)
>     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main (
> RemoteTestRunner.java:196)
> Caused by: java.lang.RuntimeException: Error setting property
> 'setStructures' of '[EMAIL PROTECTED]'.
> Cause: java.lang.IllegalArgumentException : argument type mismatch
>     at
> com.ibatis.sqlmap.engine.accessplan.PropertyAccessPlan.setProperties(
> PropertyAccessPlan.java:52)
>     at com.ibatis.sqlmap.engine.exchange.JavaBeanDataExchange.setData(
> JavaBeanDataExchange.java :112)
>     at
> com.ibatis.sqlmap.engine.mapping.result.BasicResultMap.setResultObjectValues
> (BasicResultMap.java:373)
>     at
> com.ibatis.sqlmap.engine.mapping.statement.RowHandlerCallback.handleResultObject
> (RowHandlerCallback.java :64)
>     at com.ibatis.sqlmap.engine.execution.SqlExecutor.handleResults(
> SqlExecutor.java:382)
>     at
> com.ibatis.sqlmap.engine.execution.SqlExecutor.handleMultipleResults(
> SqlExecutor.java:301)
>     at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery (
> SqlExecutor.java:190)
>     at
> com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteQuery
> (GeneralStatement.java:205)
>     at
> com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(
> GeneralStatement.java:173)
>     ... 45 more
> Caused by: java.lang.IllegalArgumentException: argument type mismatch
>     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>     at sun.reflect.NativeMethodAccessorImpl.invoke (
> NativeMethodAccessorImpl.java:39)
>     at sun.reflect.DelegatingMethodAccessorImpl.invoke(
> DelegatingMethodAccessorImpl.java:25)
>     at java.lang.reflect.Method.invoke(Method.java:597)
>     at
> com.ibatis.sqlmap.engine.accessplan.PropertyAccessPlan.setProperties (
> PropertyAccessPlan.java:46)
>     ... 53 more
>
> What am I doing wrong? Do I need interfaces for my domain objects? I
> didn't need it when using Hibernate so I thought that maybe... Or what?
>
> --
> // Jonathan
>



-- 
// Jonathan
<!--+
    | Copyright (c) 2007 Bioclipse Project
    | All rights reserved. This program and the accompanying materials
    | are made available under the terms of the Eclipse Public License v1.0
    | which accompanies this distribution, and is available at
    | http://www.eclipse.org/legal/epl-v10.html
    +-->
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE sqlMap PUBLIC "-//iBatis.com//iBatis.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd";>
<sqlMap>

<!--+
    | RESULTMAPS
    +-->
	<resultMap class="BaseObject" id="BaseObject">
		<result property="id"         column="id"                               />
		<result property="name"       column="name"                             />
		<result property="created"    column="created"                          />
		<result property="edited"     column="edited"                           />
		<result property="creator"    column="creator"    select="User.getById" />
		<result property="lastEditor" column="lastEditor" select="User.getById" />
	</resultMap>

	<resultMap class="Library" id="Library" extends="BaseObject">
		<result property="structures" column="id" select="Library.getStructures"/>
	</resultMap>
	
	<resultMap class="Structure" id="Structure" extends="BaseObject">
		<result property="library"           column="library" select="Library.getById" />
		<result property="fingerPrintString" column="fingerPrintString"                />
		<result property="smiles"            column="smiles"                           />
		<result property="moleculeCML"       column="molecule"                         />
	</resultMap>
	
	<resultMap class="User" id="User" extends="BaseObject">
		<result property="userName"      column="userName" />
		<result property="passWordMd5"   column="passWord" />
		<result property="sudoer"        column="sudoer"   />
	</resultMap>

<!--+
    | SQL FRAGMENTS
    +-->
	<sql id="BaseObject-fields">
		b.id         AS id,
		b.name       AS name,
		b.created    AS created,
		b.edited     AS edited,
		b.creator    AS creator,
		b.lastEditor AS lastEditor	
	</sql>
	
	<sql id="Structure-fields">
		s.library           AS library,
		s.fingerPrintString AS fingerPrintString,
		s.smiles            AS smiles,
		s.molecule          AS molecule
	</sql>
	
	<sql id="User-fields">
		u.userName AS userName,
		u.passWord AS passWord,
		u.sudoer   AS sudoer
	</sql>
	
<!--+
    | INSERT STATEMENTS
    +-->
	<insert id="BaseObject.insert">
		INSERT INTO BaseObject (  id,     name,     created,     edited,     creator,        lastEditor )
			            VALUES ('$id$', '$name$', '$created$', '$edited$', '$creator.id$', '$lastEditor.id$')
	</insert>
	
	<insert id="BaseObject.insertGod">
		INSERT INTO BaseObject (   id,       name   )
		                VALUES ( '$id$',   '$name$' );
	</insert>
	
	<insert id="User.insert">
		INSERT INTO User (   id,     userName,     passWord,        sudoer,     baseObject )
			      VALUES ( '$id$', '$userName$', '$passWordMd5$', '$sudoer$', '$id$'       );
	</insert>
	
	<insert id="Structure.insert">
		INSERT INTO Structure (   id,     baseObject, library,        smiles,     fingerPrintString,     molecule      )
		               VALUES ( '$id$', '$id$',     '$library.id$', '$smiles$', '$fingerPrintString$', '$moleculeCML$' ); 
	</insert>
	
	<insert id="Structure.insertWithoutLibrary">
		INSERT INTO Structure (   id,     baseObject, smiles,     fingerPrintString,     molecule      )
		               VALUES ( '$id$', '$id$',     '$smiles$', '$fingerPrintString$', '$moleculeCML$' );
	</insert>
	
	<insert id="Library.insert">
		INSERT INTO Library (   id,     baseObject )
		             VALUES ( '$id$', '$id$'       );
	</insert>
	
<!--+
    | SELECT STATEMENTS
    +-->
	<select id="Structure.getById" parameterClass="String" resultMap="Structure">
		SELECT 
			<include refid="BaseObject-fields" />, 
			<include refid="Structure-fields"  />
		FROM
			Structure s INNER JOIN BaseObject b ON
			s.baseObject = b.id
		WHERE 
			s.id = #value#
	</select>
	
	<select id="User.getById" parameterClass="String" resultMap="User">
		SELECT 
			<include refid="BaseObject-fields" />,
			<include refid="User-fields"       />
		FROM
			User u INNER JOIN BaseObject b ON
			u.baseObject = b.id
		WHERE 
			u.id = #value#
	</select>
	
	<select id="Library.getById" resultMap="Library" parameterClass="String">
		SELECT 
			<include refid="BaseObject-fields" />
		FROM
			Library l INNER JOIN BaseObject b ON
			l.baseObject = b.id
		WHERE 
			l.id = #value#
	</select>
	
	<select id="Library.getStructures" resultMap="Structure" parameterClass="String">
		SELECT 
			<include refid="BaseObject-fields" />,
			<include refid="Structure-fields"  />
		FROM
			Structure s INNER JOIN BaseObject b ON
			s.baseObject = b.id
		WHERE 
			s.library = #value#
	</select>
	
	<select id="Structure.getAll" resultMap="Structure">
		SELECT
			<include refid="BaseObject-fields" />, 
			<include refid="Structure-fields"  />
		FROM
			Structure s INNER JOIN BaseObject b ON
			s.baseObject = b.id
	</select>
	
	<select id="Library.getAll" resultMap="Library">
		SELECT
			<include refid="BaseObject-fields" />
		FROM
			Library l INNER JOIN BaseObject b ON
			l.baseObject = b.id
	</select>

	<select id="User.getAll" resultMap="User">
		SELECT 
			<include refid="BaseObject-fields" />,
			<include refid="User-fields"       />
		FROM
			User u INNER JOIN BaseObject b ON
			u.baseObject = b.id
	</select>
	
<!--+
    | DELETE STATEMENTS
    +-->	
	<delete id="User.delete" parameterClass="String">
		DELETE FROM User
		WHERE id='$value$';
	</delete>
	
	<delete id="Structure.delete" parameterClass="String">
		DELETE FROM Structure
		WHERE id='$value$';
	</delete>
	
	<delete id="Library.delete" parameterClass="String">
		DELETE FROM Library
		WHERE id='$value$';
	</delete>
	
<!--+
    | UPDATE STATEMENTS
    +-->
    <update id="BaseObject.update" parameterClass="BaseObject">
    	UPDATE 
    		BaseObject
    	SET 
			name       = '$name$',
			created    = '$created$',
			edited     = '$edited$',
			creator    = '$creator.id$',
			lastEditor = '$lastEditor.id$'	
		WHERE
			id = '$id$'
    </update>
    
    <update id="User.update" parameterClass="User">
    	UPDATE 
    		User
    	SET 
	    	userName = '$userName$',
			passWord = '$passWordMd5$',
			sudoer   = '$sudoer$'
		WHERE
			id = '$id$'
    </update>
    
    <update id="Library.update" parameterClass="Library">
    	
    </update>
    
    <update id="Structure.update" parameterClass="Structure">
    	UPDATE 
    		Structure
    	SET 
	    	library           = '$library.id$',
	    	smiles            = '$smiles$',
	    	fingerPrintString = '$fingerPrintString$',
	    	molecule          = '$moleculeCML$'
		WHERE
			id = '$id$'
    </update>
    
</sqlMap>
/*******************************************************************************
 * Copyright (c) 2007 Bioclipse Project
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     
 *******************************************************************************/

package net.bioclipse.structuredb.domain;

import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.UUID;

/**
 * A baseclass for all domain objects. 
 * It creates a unique id for the object and contains code for comparisons 
 * between two domain objects.
 * 
 * @author jonalv
 */
public class BaseObject {

	private String id; //36 chars long unique id 
	private String name;
	
	private User creator;
	private User lastEditor;
	
	private Timestamp created;
	private Timestamp edited;
	
	public BaseObject() {
		
		this.id = UUID.randomUUID().toString();
		name = "name";
	}
	
	/**
	 * Creates a unique id and sets a name for the 
	 * BaseObject
	 * 
	 * @param name 
	 */
	public BaseObject( String name ) {
		
		this.name = name;
		this.id   = UUID.randomUUID().toString();
	}

	/**
	 * Creates a new BaseObject that is an exact copy of the 
	 * given instance with the same id.
	 * 
	 * @param obj
	 */
	public BaseObject( BaseObject obj ) {
		
		this.id         = obj.id;
		this.name       = obj.name;
		this.creator    = obj.getCreator();
		this.lastEditor = obj.getLastEditor();
	}

	/**
	 * @return the id
	 */
	public String getId() {
		return id;
	}

	/**
	 * @param id the id to be set
	 */
	public void setId(String id) {
		this.id = id;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name new name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 * 
	 * Final since the id is a sufficient hashcode.
	 */
	@Override
	public final int hashCode() {
		
		return id.hashCode(); 
	}

	/**
	 * Checks whether two objects correspond to the same database row.
	 * Final since we only want equals to check the id for the domain objects.
	 * This implementation provides an equals method that doesn't break the 
	 * equals / hashcode contract and works with database mapped objects.
	 * In order to check whether they correspond to two identical versions of 
	 * said row use: <code>hasValuesEqualTo</code>
	 * 
	 * @param anObject - the object to compare this String  against.
	 * @return true if the domain object refer to the same database row; false otherwise.
	 */
	@Override
	public final boolean equals(Object obj) {
		if( !(obj instanceof BaseObject) ) {
			return false;
		}
		return id.equals( ( (BaseObject)obj ).getId() );
	}

	/**
	 * @param obj a BaseObject to be compared
	 * @return whether all fields (including id) of the given object equals this objects 
	 * fields
	 */
	public boolean hasValuesEqualTo( BaseObject obj ) {
		if( obj == null ) {
			return false;
		}
		if( this.creator != null) {
			if( !this.creator.hasValuesEqualTo(obj.getCreator()) ) {
				return false;
			}
		}
		if( this.lastEditor != null ) {
			if( !this.creator.hasValuesEqualTo(obj.getLastEditor()) ) {
				return false;
			}
		}
		
		return name.equals( obj.name ) 
		      && id.equals(obj.id);
	}
	
	/**
	 * Checks that the objects in both sets are alike and that no object exists in one set 
	 * but not in the other.
	 * 
	 * @param set1
	 * @param set2
	 * @return whether the sets are alike
	 */
	/*
	 * This can not be done with equals since it is used for checking id
	 */
	protected boolean objectsInHasSameValues( Set<? extends BaseObject> set1, 
			                                  Set<? extends BaseObject> set2 ) {

		if( set1.size() != set2.size() ) {
			return false;	
		}
		HashMap<String, BaseObject> hash2 = new HashMap<String, BaseObject>();
		for( BaseObject obj : set2) {
			hash2.put(obj.getId(), obj);
		}
		
		for( BaseObject obj : set1) {
			if( hash2.get(obj.getId()) == null || !hash2.get( obj.getId() ).hasValuesEqualTo(obj) ) {
				return false;
			}
		}
		return true;
	}
	
	/**
	 * Checks that the objects in both lists are alike and in the same order.
	 * 
	 * @param list1
	 * @param list2
	 * @return whether the sets are alike
	 */
	/*
	 * This can not be done with equals since it is used for checking id
	 */
	protected boolean objectsInHasSameValues( List<? extends BaseObject> list1, 
			                                  List<? extends BaseObject> list2 ) {

		if( list1.size() != list2.size() ) {
			return false;	
		}
	
		for (int i = 0; i < list1.size(); i++) {
			if( !list2.get( i ).hasValuesEqualTo( list1.get(i) ) ) {
				return false;
			}
		}
		return true;
	}

	public void setCreator(User creator) {
		User oldCreator = this.creator;
		this.creator = creator;
		
		if( oldCreator != null && oldCreator != creator ) {
			oldCreator.removeCreatedBaseObject(this);
		}
		
		if( creator != null && !creator.getCreatedBaseObjects().contains(this) ) {
			creator.addCreatedBaseObject( this );
		}
	}

	public void setLastEditor(User editor) {
		this.lastEditor = editor;
		
	}

	public User getCreator() {
		return creator;
	}

	public User getLastEditor() {
		return lastEditor;
	}

	public Timestamp getCreated() {
		return created;
	}

	public void setCreated(Timestamp created) {
		this.created = created;
	}

	public Timestamp getEdited() {
		return edited;
	}

	public void setEdited(Timestamp edited) {
		this.edited = edited;
	}
}
/*******************************************************************************
 * Copyright (c) 2007 Bioclipse Project
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     
 *******************************************************************************/

package net.bioclipse.structuredb.domain;

import java.util.HashSet;
import java.util.Set;

import org.openscience.cdk.AtomContainer;

public class Library extends BaseObject {

	private Set<Structure> structures;
	
	public Library() {
		super();
		structures = new HashSet<Structure>();
	}

	public Library(Library library) {
		super(library);
		this.structures = new HashSet<Structure>( library.getStructures() );
	}

	public Library(String name) {
		super(name);
		structures = new HashSet<Structure>();
	}
	
	/* (non-Javadoc)
	 * @see net.bioclipse.structuredb.domain.BaseObject#hasValuesEqualTo(net.bioclipse.structuredb.domain.BaseObject)
	 */
	public boolean hasValuesEqualTo( BaseObject obj ) {
		
		if( !super.hasValuesEqualTo(obj) ) {
			return false;
		}
		if( !(obj instanceof Library) ) {
			return false;
		}
		Library library = (Library)obj;
		return objectsInHasSameValues(library.getStructures(), structures);
	}

	/**
	 * @return the structures in the library 
	 */
	public Set<Structure> getStructures() {
		return structures;
	}

	/**
	 * @param structures the structures to set
	 */
	public void setStructures(Set<Structure> structures) {
		this.structures = structures;
	}

	/**
	 * Adds a structure to the library
	 * 
	 * @param structure the structure to add
	 */
	public void addStructure(Structure structure) {
		structures.add(structure);
		if( structure.getLibrary() != this ) {
			structure.setLibrary(this);
		}
	}

	/**
	 * Removes a structure from the library
	 * 
	 * @param structure the structure to remove
	 */
	public void removeStructure(Structure structure) {
		structures.remove(structure);
		if( structure.getLibrary() != null ) {
			structure.setLibrary(null);
		}
	}
}
package net.bioclipse.structuredb.persistency.dao;

import java.sql.Timestamp;
import java.util.List;

import net.bioclipse.hsqldb.HsqldbUtil;
import net.bioclipse.structuredb.domain.BaseObject;
import net.bioclipse.structuredb.domain.User;
import net.bioclipse.structuredb.persistency.HsqldbTestServerManager;

import org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests;
import org.springframework.transaction.annotation.Transactional;

/**
 * Generic base class for testing the daos. Performs tests of the basic dao methods.
 * Usage: Extend and give the domain class to be tested as generic class parameter.
 *        When extra testsmethods are written setUpTestEnvironment() needs to be called
 *        to initiate the dao.
 * 
 * @author jonalv
 *
 * @param <DomainType>
 */
public abstract class GenericDaoTest<DomainType extends BaseObject> extends AbstractAnnotationAwareTransactionalTests  {

	static {
		HsqldbTestServerManager.INSTANCE.startServer();
		HsqldbTestServerManager.INSTANCE.setupTestEnvironment();
	}
	
	protected IGenericDao<DomainType> dao;
	
	private Class<DomainType> domainClass;
	
	protected User god;
	
	protected DomainType object1;
	protected DomainType object2;

	/**
	 * @param c Class for the domain type to be tested
	 */
	public GenericDaoTest( Class<DomainType> c ) {
		super();
		this.domainClass = c;
	}
	
	@Transactional
	public void onSetUpInTransaction() throws Exception {
		super.onSetUpInTransaction();
		
		god = new User("God", "god", "fiat lux");
		
		IUserDao userDao = (IUserDao) applicationContext.getBean("userDao");
		
		userDao.persistGodObject(god);
		String daoName = domainClass.getSimpleName() + "Dao";
		daoName = firstToLowerCase(daoName);
		dao = (IGenericDao<DomainType>) applicationContext.getBean(daoName);
		try {
			object1 = domainClass.newInstance();
			object2 = domainClass.newInstance();
			object2.setName("otherName");
			setCreatorAndEditor(object1);
			setCreatorAndEditor(object2);
		} 
		catch (Exception e) {
			fail( e.toString() );
		}
		dao.insert(object1);
		dao.insert(object2);
	}
	
	private String firstToLowerCase(String daoName) {
		return Character.toLowerCase( daoName.charAt(0) ) + daoName.substring(1);
	}

	protected void setCreatorAndEditor(BaseObject object) {
		Timestamp now = new Timestamp( System.currentTimeMillis() );
		object.setCreated(now);
		object.setEdited(now);
		object.setCreator(god);
		object.setLastEditor(god);
	}

	/**
	 * tests getting all objects of the domain type handled by the tested dao
	 */
	public void testGetAll() {
		List<DomainType> objects = dao.getAll();
		assertTrue( objects.contains(object1) );
		assertTrue( objects.contains(object2) );
	}
	
	/**
	 * tests getting an instance by id of the domain type handled by the tested dao
	 */
	public void testGetById() {
		DomainType loadedObject1 = dao.getById( object1.getId() );
		assertNotNull( "The lodaded object should not be null", loadedObject1 );
		assertTrue( "The loaded object should have values equal to the original object", object1.hasValuesEqualTo(loadedObject1) );
		assertNotSame( "The loaded object and the original object shuold not be the same",  object1, loadedObject1 );
	}
	
	/**
	 * tests deleting of an instance of the domain type handled by the tested dao 
	 */
	public void testDelete() {
		dao.delete( object1.getId() );
		DomainType loadedObject1 = dao.getById( object1.getId() );
		assertNull(loadedObject1);
		String sql = "SELECT COUNT(*) FROM " + domainClass.getSimpleName() + " WHERE id='" + object1.getId() + "'";
		System.out.println(sql);
		int numberof = jdbcTemplate.queryForInt(sql);
		assertEquals( "The object should be deleted", 0, numberof);
	}
	
	/**
	 * tests updating an instance of the domain type handled by the tested dao
	 */
	public void testUpdate() {
		DomainType loadedObject1 = dao.getById( object1.getId() );
		assertFalse(loadedObject1.getName().equals("edited"));
		loadedObject1.setName("edited");
		dao.update(loadedObject1);
		loadedObject1 = dao.getById( object1.getId() );
		assertEquals("name should have changed", "edited", loadedObject1.getName());
	}
	
	protected String[] getConfigLocations() {
		return new String[] { "classpath:applicationContext.xml" };
	}
}
/*******************************************************************************
 * Copyright (c) 2007 Bioclipse Project
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     
 *******************************************************************************/
package net.bioclipse.structuredb.persistency.dao;

import net.bioclipse.structuredb.domain.Library;

/**
 * @author jonalv
 *
 */
public class LibraryDaoTest extends GenericDaoTest<Library> {

	public LibraryDaoTest() {
		super(Library.class);
	}
}

Reply via email to