I am writing a unit test to for my AbstractHibernateRepository save method. I'm using spring test runner but I get the following exception when it runs:
org.hibernate.service.UnknownServiceException: Unknown service requested [org.hibernate.engine.jdbc.connections.spi.ConnectionProvider]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:201)
My Test:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/spring-hibernate.xml")
public class AbstractHibernateRepoTest extends AbstractHibernateRepo<Video> {
@Autowired private SessionFactory sessionFactory;
private Video video;
public AbstractHibernateRepoTest()
{
super(Video.class);
}
@Before
public void setUp ()
{
video = new Video();
video.setId("xyz");
video.setName("Video Name");
video.setSrc("Source");
video.setThumbnail("Thumbnail");
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(video) ;
session.close();
}
@Test
public void testSaveMethod ()
{
video.setId("asa");
String id = (String) save(video);
Assert.assertEquals(video.getId(), id);
}
@After
public void breakDown ()
{
sessionFactory.close();
}
}
Repository:
@Autowired private SessionFactory sessionFactory;
private final Class<T> clazz;
public AbstractHibernateRepo(Class<T> clazz)
{
this.clazz = clazz;
}
@SuppressWarnings("unchecked")
@Transactional(rollbackFor = HibernateException.class)
@Override
public T findById(Serializable id)
{
if (id == null)
throw new NullPointerException();
return (T) getSessionFactory().getCurrentSession().get(getClazz(), id);
}
@Override
@Transactional(rollbackFor = HibernateException.class)
public Serializable save(T entity)
{
if (entity == null)
throw new NullPointerException();
return getSessionFactory().getCurrentSession().save(entity);
}
@Override
@Transactional(rollbackFor = HibernateException.class)
public void delete(T entity)
{
if (entity == null)
throw new NullPointerException();
getSessionFactory().getCurrentSession().delete(entity);
}
@Override
@Transactional(rollbackFor = HibernateException.class)
public void update(T entity)
{
if (entity == null)
throw new NullPointerException();
getSessionFactory().getCurrentSession().update(entity);
}
}
Spring Config:
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE"/>
<property name="username" value="someuser"/>
<property name="password" value="somepassword"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.package.model"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="dataSource" ref="dataSource"/>
</bean>
What's causing this problem and how can I fix it?
I might be totally off here, but to me this seems to be a session handling exception. In @Before
you open and close session, then in save()
you get the current session, which is maybe the one you just closed, leading to an exception. Try if it works if you don't close it in @Before
(I know it's not the solution, just to test the theory). You can also try opening a new session in repository instead of getting the current one (also not the solution). The only difference I see compared with our working test setup is that in @Before
we also call our repository methods, marked as @Transactional
, instead of creating a session directly.