Question

I've just upgraded a Spring web application from Hibernate 3.6 to 4.2, and done all the necessary changes as far as I can see. The application itself seems to run fine, but some tests use Hibernate via Spring's application context test support, and these now fail sporadically with this error:

Caused by: org.hibernate.service.UnknownServiceException: Unknown service requested [org.hibernate.service.jdbc.connections.spi.ConnectionProvider]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:126)
at org.hibernate.internal.AbstractSessionImpl.getJdbcConnectionAccess(AbstractSessionImpl.java:261)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.<init>(JdbcCoordinatorImpl.java:97)
at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.<init>(TransactionCoordinatorImpl.java:87)
at org.hibernate.internal.SessionImpl.<init>(SessionImpl.java:253)
at org.hibernate.internal.SessionFactoryImpl$SessionBuilderImpl.openSession(SessionFactoryImpl.java:1599)
at org.hibernate.internal.SessionFactoryImpl.openSession(SessionFactoryImpl.java:965)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:412)

They seem to run more reliably when run in default filesystem order, but I am running them in random order at the moment to reproduce it more easily. Once this error happens once, all similar tests after that seem to fail too. The tests are set up with the @DirtiesContext annotation so the Spring test runner ought to be recreating a new ApplicationContext (and so SessionFactory and HSQLDB mem DB) with each class. So there shouldn't be anything leaking from one test class to the next.

Any ideas? Not having a ConnectionProvider sounds like Hibernate is either still starting up, or in the middle of shutting down.

Was it helpful?

Solution 2

We've got the tests passing now. It was actually a problem with our transaction handling leaking into non-transactional tests. Our transaction support extended Spring's TransactionAspectSupport, and with Hibernate 3 this used to work in non-transactional tests by doing nothing. In Hibernate 4 it now fails in a roundabout way, when it tries to create a transaction with a shut-down session factory.

We modified the way tests were set up so that it wouldn't try doing any transactional stuff at all unless we were in a transactional test, and they now pass happily.

Moral: One of the perils of using a singleton is that it can easily leak stuff across tests.

OTHER TIPS

You should create Session Factory object only once in application and you should not destroy in your whole application. If you are trying to the close the once created session factory object and want to use same object so you will get this above exception ie. Error creating Session: org.hibernate.service.UnknownServiceException: Unknown service requested [org.hibernate.engine.jdbc.connections.spi.ConnectionProvider] So in above scenario you should create the hibernate util and define fields as below:

import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {

private static Configuration configuration;
private static StandardServiceRegistry builder;
private static SessionFactory factory;

static {
try {
configuration = new Configuration().configure("/com/hibernate/hibernate.cfg.xml");
builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
factory = configuration.buildSessionFactory(builder);
} catch (HibernateException he) {
System.err.println("Error creating Session: " + he);
throw new ExceptionInInitializerError(he);
}
}

public static SessionFactory getSessionFactory() {
return factory;
}

public static void closeSessionFactory() {
if (factory != null) {
try {
StandardServiceRegistryBuilder.destroy(builder);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

Something like this happened to me before. It was solved when I changed the IP of the database from 127.0.0.1 to 192.168.1.27 (the IP of my computer in my network, it can be found doing ip config in windows or ifconfig in linux). It might not be a permanent solution, but it dodges a bullet.

Session object in Hibernate is not thread safe, you should not use the same session in different threads, unless you synchronize access to Session object.

And if you really want to use that trick then I like to say you that every time clear and close session after transaction is complete. Or just use openSession() so that way your program will work and will execute.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top