I try to be quick.
In fact, one of my jUnit test is failing when running the Maven command of my project (mvn install, so with the Surefire plugin) while it's successful when I run it in Eclipse.
I tried many things and the only difference I managed to see is that : - With Maven/Surefire in debug-mode, in the Hibernate-SessionFactory I have only 3 EntityPersister instances - With Eclipse in debug perspective, I could see 6 EntityPersister instances (in fact the number of annotatedClasses I have in my project)
Here is my Spring configuration file ("dataSource" is defined in another project, I don't put the DAO classes) :
<beans ...>
<!-- le gestionnaire de BLOB / CLOB de chez Spring -->
<bean id="lobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" />
<!-- Hibernate SessionFactory Definition -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
<property name="dataSource">
<ref bean="datasource" />
</property>
<property name="packagesToScan">
<list>
<value>com.wft.model</value>
<value>com.wft.model.user</value>
</list>
</property>
<!--
<property name="annotatedClasses">
<list>
<value>com.wft.model.Project</value>
<value>com.wft.model.Authors</value>
<value>com.wft.model.user.User</value>
<value>com.wft.model.user.Administrator</value>
<value>com.wft.model.user.Gamer</value>
<value>com.wft.model.user.Organizer</value>
</list>
</property>
-->
</bean>
<!-- Hibernate Transaction Manager Definition -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- TODO: Switch to annotations for transactions
<tx:annotation-driven/>
-->
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager" />
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<!-- -->
<bean id="autoProxyCreator"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<idref local="transactionInterceptor" />
</list>
</property>
<property name="beanNames">
<list>
<value>*DAO</value>
</list>
</property>
</bean>
<bean id="projectDAO" class="com.wft.service.dao.impl.ProjectDAO">
<constructor-arg>
<value>com.wft.model.Project</value>
</constructor-arg>
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<bean id="userDAO" class="com.wft.service.dao.impl.UserDAO">
<constructor-arg>
<value>com.wft.model.user.User</value>
</constructor-arg>
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
</beans>
And the test class :
public class TestDAO extends
AbstractTransactionalDataSourceSpringContextTests {
private IUserDAO userDAO;
private IProjectDAO projectDAO;
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
protected String[] getConfigLocations() {
return new String[] { "classpath*:myapp-persistence-tech.xml",
"classpath*:datasource_mysql.xml" };
}
@Override
protected boolean isDefaultRollback() {
return false;
}
@Override
protected boolean isRollback() {
return false;
}
/**
* Spring will automatically inject userDAO object on startup
*
* @param userDAO
*/
public void setUserDAO(IUserDAO userDAO) {
this.userDAO = userDAO;
}
/**
* Spring will automatically inject projectDAO object on startup
*
* @param projectDAO
*/
public void setProjectDAO(IProjectDAO projectDAO) {
this.projectDAO = projectDAO;
}
public void test1() {
System.out.println("Session Factory : "+sessionFactory);
@SuppressWarnings("unused")
SessionFactoryImpl sfImpl = (SessionFactoryImpl)sessionFactory;
Administrator admin = new Administrator("admin", "admin");
User user1 = new User("user1", "user1");
User user2 = new User("user2", "user2");
for (User user : userDAO.findAll()) {
if (user instanceof Administrator) {
System.out.println("Deleting administrator");
} else {
System.out.println("Deleting user");
}
userDAO.delete(user);
}
userDAO.add(user1);
userDAO.add(admin);
// dao.add(user2);
System.out.println();
assertTrue(true);
}
}
When I debug the jUnit in Eclipse, I can see all the EntityPersisters :
entityPersisters HashMap<K,V> (id=75)
entrySet HashMap$EntrySet (id=87)
keySet null
loadFactor 0.75
modCount 6
size 6
table HashMap$Entry<K,V>[16] (id=95)
threshold 12
values HashMap$Values (id=136)
but when remote-debugging Surefire on the port 5005, I only got 3 …
and it ends with :
test1(com.wft.service.services.TestDAO) Time elapsed: 2.139 sec <<< ERROR!
org.hibernate.MappingException: Unknown entity: com.wft.model.user.Administrator
at org.hibernate.impl.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:580)
One important thing maybe (is that Administrator is a subclass of User) :
@Entity
@Table(name = "USER")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="DTYPE", discriminatorType=DiscriminatorType.STRING, columnDefinition="VARCHAR(32) DEFAULT \"ROLE_USER\"", length=32)
@DiscriminatorValue(value="ROLE_USER")
@ForceDiscriminator
public class User extends LightEntity implements Serializable {}
@Entity
@DiscriminatorValue(value="ROLE_ADMINISTRATOR")
@ForceDiscriminator
public class Administrator extends User {}
but the inheritance does not seem to be the root cause.
Is someone aware of such a discrepancy between the 2 environments (Maven+Surefire vs Eclipse+jUnit launcher) ? Does it look like a bug in surefire (or somewhere else) or a wrong usage of one of the frameworks involved ?