I'm trying to host my first backend server via heroku. I have already hosted a mysql server (also on heroku) that I have been able to connect to from my local using both my java servlet and mysql workbench.
I used heroku's git integration to push my servlet to their servers, and as far as I can tell, my tomcat server IS running. When I try to hit one of my urls I get an error message.
The only one I can see that matters is the last one.
java.lang.NoClassDefFoundError: Could not initialize class com.DatabaseHandler.DBHandler.
From what I can understand, this is being caused because my static initialization for my session handler is failing.
I've double checked all of my connections, made sure my mysql drivers were correct, added the mysql driver to the buildpath just in case heroku can't find it, and a host of other things.
Most of my google searches have come up fruitless with solutions I've already tried, or answers that don't pertain to my problem.
Article Controller
public class ArticleService {
Session session;
public ArticleService() {
this.session = DBHandler.getSessionFactory().openSession();
}
public List<Article> getAllArticles() {
List<Article> list = session.createQuery("from Article").list();
return list;
}
public ArticleModelView getArticlePage(int pageNumber, int itemsPerPage) {
ArticleModelView avm = new ArticleModelView();
Query q = session.createQuery("from Article");
q = q.setFirstResult(pageNumber*itemsPerPage);
q = q.setMaxResults(itemsPerPage);
avm.articles = q.list();
int temp = session.createQuery("from Article").list().size();
temp = temp % itemsPerPage == 0 ? temp/itemsPerPage - 1: temp/itemsPerPage;
avm.maxPageSize = temp;
return avm;
}
}
Database Handler
public class DBHandler
{
private static final SessionFactory sessionFactory;
static {
try {
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static void shutdown() {
getSessionFactory().close();
}
}
Hibernate Config
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">*******?reconnect=true</property>
<property name="hibernate.connection.password">******</property>
<property name="hibernate.connection.username">******</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">update</property>
<mapping class="com.dailybagel.user.resources.User"/>
<mapping class="com.dailybagel.article.resources.Article"/>
</session-factory>
</hibernate-configuration>
When I visit that url with local host the application correctly pings the hosted mysql server and returns the contents of that table.
The goal is to get the hosted servlet to do that same thing.
So it looks like Heroku misplaces the Hibernate config file, or it's lost, or something of the sort. Adding your config variable to the Session Handler resolves the issue.
I don't really understand why it gets misplaced, but hopefully this will help someone!
static {
try {
Properties prop= new Properties();
prop.setProperty("hibernate.connection.url", "*********");
prop.setProperty("hibernate.connection.username", "********");
prop.setProperty("hibernate.connection.password", "********");
prop.setProperty("dialect", "org.hibernate.dialect.MySQLInnoDBDialect");
sessionFactory = new AnnotationConfiguration()
.addPackage("com.dailybagel.user.resources")
.addPackage("com.dailybagel.article.resources")
.addAnnotatedClass(User.class)
.addAnnotatedClass(Article.class)
.addProperties(prop)
.buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
If anyone know why this happens, I'd love to know more about it
Related
I'm getting this error: org.hibernate.HibernateException: No CurrentSessionContext configured!
when trying to connect to Heroku Postgres DB.
this is my hibernate configuration (i called it: hibernateUser.cfg.xml):
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.connection.url">jdbc:postgresql://ec2-54-243-213-188.compute-1.amazonaws.com:5432/dess6n165jarrv</property>
<property name="hibernate.connection.username">user</property>
<property name="hibernate.connection.password">password</property>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="hibernate.default_schema">dess6n165jarrv</property>
<property name= "hbm2ddl.auto">update</property>
<property name="hibernate.current_session_context_class">thread</property>
</session-factory>
</hibernate-configuration>
enter code here
I'm implementing this as a singleton :
public static HibernateUserDAO getInstance(HttpServletResponse response) throws IOException
{
instance = new HibernateUserDAO();
if (instance == null)
{
userFactory = new Configuration().configure("hibernateUser.cfg.xml").addAnnotatedClass(AppUser.class).buildSessionFactory();
}
return instance;
}
public void addNewUser(AppUser user) throws UserExceptionHandler, IOException
{
Session session = null;
int id = 0;
try
{
session = userFactory.getCurrentSession();
session.beginTransaction();
session.save(user);
session.getTransaction().commit();
}catch (HibernateException e)
{
if (session.getTransaction() != null) session.getTransaction().rollback();
throw new HibernateException (e);
}finally
{
try
{session.close();}
catch (HibernateException e)
{
throw new UserExceptionHandler("Warnning!! connection did'nt close properly");
}
}
if (id != 0)
System.out.println("User created successfully");
}
enter code here
I'm getting the error on this line:
session = userFactory.getCurrentSession();
I think the error is in my configuration file but I cant see where is the problem is (I read a couple of examples and I copy it)
You need to set your connection parameters dynamically like this:
Map<String,String> jdbcUrlSettings = new HashMap<>();
String jdbcDbUrl = System.getenv("JDBC_DATABASE_URL");
if (null != jdbcDbUrl) {
jdbcUrlSettings.put("hibernate.connection.url", System.getenv("JDBC_DATABASE_URL"));
}
registry = new StandardServiceRegistryBuilder().
configure("hibernate.cfg.xml").
applySettings(jdbcUrlSettings).
build();
This way, they are not hard coded, and will pick up changes made by the platform. For more info see Using the DATABASE_URL with Hibernate.
This is very weird to me...
so this...would throw ClassCastException
MyStatus object = Main.getSession().get(MyStatus.class, 1);
but this will not...
Object object = Main.getSession().get(MyStatus.class, 1);
I also did instanceof the Object returned above. It is clearly an MyStatus object and it has all correct data got from DB. My Main class is auto-generated by Intellij.
public class Main {
private static final SessionFactory ourSessionFactory;
static {
try {
Configuration configuration = new Configuration();
configuration.configure();
ourSessionFactory = configuration.buildSessionFactory();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static Session getSession() throws HibernateException {
return ourSessionFactory.openSession();
}
public static void main(final String[] args) throws Exception {
final Session session = getSession();
try {
System.out.println("querying all the managed entities...");
final Metamodel metamodel = session.getSessionFactory().getMetamodel();
for (EntityType<?> entityType : metamodel.getEntities()) {
final String entityName = entityType.getName();
final Query query = session.createQuery("from " + entityName);
System.out.println("executing: " + query.getQueryString());
for (Object o : query.list()) {
System.out.println(" " + o);
}
}
} finally {
session.close();
}
}
}
here is my hibernate.cfg.xml file
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/testdb</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">test</property>
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
<mapping resource="/com/test/app/MyStatus.hbm.xml" class="com.test.app.models.MyStatus" />
</session-factory>
</hibernate-configuration>
and here is the Exception thrown
javax.servlet.ServletException: java.lang.ClassCastException: com.test.MyStatus cannot be cast to com.test.MyStatus
org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:489)
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228)
1) When you have ClassCastException on the same class (same name and package) it means that you are dealing with different ClassLoaders.
If you print MyStatus.class.getClassLoader() and object.getClass().getClassLoader() you will see that they are different instances of ClassLoader.
This situation can happen when you have the same class in your Glassfish classpath and in your war.
2) Another weird thing is that you have MyStatus declared as com.test.app.models.MyStatus in your hibernate.cfg.xml but the exception says com.test.MyStatus. These are two different classes but most likely are not related to the ClassCastException issue.
Have you tried to cast the result ?
MyStatus object = (MyStatus) Main.getSession().get(MyStatus.class, 1);
And as said #tsolakp, the error is weird, two packages seem to be loaded.
We provide db credential in hibernate.cfg.xml as
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.url">url</property>
<property name="hibernate.connection.username">username</property>
<property name="hibernate.connection.password">password</property>
<session-factory>
<hibernate-configuration>
Either we can provide these properties here or in hibernate.properties in classpath. But I want them to come from an external file. I couldn't find a way in hibernate to change the path of default hibernate.properties file.
Please help.
[EDIT]
The method in java which generates sessionFactory object
public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
// Create the session factory from hibernate.cfg.xml
Configuration configuration = new Configuration();
StandardServiceRegistryBuilder serviceRegistryBuilder =
new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
return configuration.buildSessionFactory(serviceRegistryBuilder.build());
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
Programmatically, you can load XML and properties like this:
public class MyHibernate {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
URL r1 = MyHibernate.class.getResource("/hibernate.cfg.xml");
Configuration c = new Configuration().configure(r1);
try {
InputStream is = MyHibernate.class.getResourceAsStream("/hibernate.properties");
Properties props = new Properties();
props.load(is);
c.addProperties(props);
} catch (Exception e) {
LOG.error("Error reading properties", e);
}
return c.buildSessionFactory();
} catch (Throwable ex) {
LOG.error("Error creating SessionFactory", ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
Through Spring
You can use a PropertiesFactoryBean to read-in the properties from your file and configure your LocalSessionFactoryBean:
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<property name="hibernateProperties">
<bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location">path-to-properties-file</property>
</bean>
</property>
...
</bean>
Hope it be useful.
I recently started using hibernate along with c3p0 as the ORM in my application. However, when I close the session factory, the connection pool does not close itself! This is the one and only place in my application where I do anything with a session.
StatelessSession session = null;
Transaction transaction = null;
try {
session = sessionFactory.openStatelessSession();
transaction = session.beginTransaction();
List<Thingy> list = session.getNamedQuery("getAvailableThingy").list();
transaction.commit();
return list;
} catch (Exception error) {
if (transaction != null) {
transaction.rollback();
}
throw error;
} finally {
if (session != null) {
session.close();
}
}
This is my hibernate.cfg.xml configuration file
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="javax.persistence.validation.mode">none</property>
<property name="hibernate.connection.release_mode">after_transaction</property>
<property name="hibernate.c3p0.minPoolSize">1</property>
<property name="hibernate.c3p0.maxPoolSize">2</property>
<property name="hibernate.c3p0.acquireIncrement">1</property>
<property name="hibernate.c3p0.initialPoolSize">1</property>
<property name="hibernate.c3p0.timeout">30</property>
<property name="hibernate.c3p0.maxIdleTimeExcessConnections">5</property>
<property name="hibernate.c3p0.idleConnectionTestPeriod">300</property>
</session-factory>
</hibernate-configuration>
Note that the reason for the very short idle connection it that its the only way I found yet to make my integration tests to pass. They open and close the session factory a lot and thus I always run out of connections. As we are at the beginning of the project, I guess it's not a very sustainable strategy in the long run.
An "interesting" thing to note is that despite the fact that I set the initial connection pool to one, c3p0 still try to open two connection on start. My guess is that there is some kind of hidden session somewhere that don't get closed (but where? beat me).
So how can I get that annoying connection pool to close itself up?
Additional info :
how I create and destroy my session factory
import static com.google.common.base.Preconditions.*;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Provides;
#Singleton
public class PostgisConnection implements Provider<SessionFactory>, AutoCloseable {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final ConnectionInfo connectionInfo;
private SessionFactory sessionFactory = null;
#Inject
public PostgisConnection(ConnectionInfo connectionInfo) {
this.connectionInfo = connectionInfo;
}
public AutoCloseable open() {
checkState(sessionFactory == null, "Connections to postgis are already open");
logger.info("Creating sessionFactory for connection to postgis: {}", connectionInfo.getJdbcUrl());
sessionFactory = newPostgisSessionFactory(connectionInfo);
return this;
}
#Override
public void close() throws Exception {
try {
if (sessionFactory != null) {
logger.info("Closing sessionFactory for postgis: {}", connectionInfo.getJdbcUrl());
sessionFactory.close();
checkState(sessionFactory.isClosed(), "Session factory should be closed at this point");
}
} catch (Exception error) {
logger.error("Error closing SessionFactory", error);
}
}
#Provides
public SessionFactory get() {
return sessionFactory;
}
public static SessionFactory newPostgisSessionFactory(ConnectionInfo connectionInfo) {
Configuration configuration = configurationWith(connectionInfo);
return configuration.buildSessionFactory(registryFrom(configuration));
}
private static Configuration configurationWith(ConnectionInfo connectionInfo) {
Configuration configuration = new Configuration();
setConnectionInfo(connectionInfo, configuration);
configuration.addURL(PostgisConnection.class.getResource("mapping.hbm.xml"));
configuration.configure(PostgisConnection.class.getResource("hibernate.cfg.xml"));
return configuration;
}
private static void setConnectionInfo(ConnectionInfo connectionInfo, Configuration configuration) {
configuration.setProperty("hibernate.connection.url", connectionInfo.getJdbcUrl());
configuration.setProperty("hibernate.connection.username", connectionInfo.getUsername());
configuration.setProperty("hibernate.connection.password", connectionInfo.getPassword());
}
private static ServiceRegistry registryFrom(Configuration configuration) {
return new ServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.buildServiceRegistry();
}
}
Hibernate version : 4.1.10.Final
C3p0 version : 0.9.1.2
I had the same issue and successfully used the work-around offered in this bug report:
private void closeSessionFactory(SessionFactory factory) {
if(factory instanceof SessionFactoryImpl) {
SessionFactoryImpl sf = (SessionFactoryImpl)factory;
ConnectionProvider conn = sf.getConnectionProvider();
if(conn instanceof C3P0ConnectionProvider) {
((C3P0ConnectionProvider)conn).close();
}
}
factory.close();
}
You have to reference the hibernate-c3p0-4.x.x jar.
I had the same issue and successfully used the ehnanced (January 2014) work-around offered in this bug report:
private static boolean closeSessionFactoryIfC3P0ConnectionProvider(SessionFactory factory) {
boolean done = false;
if(factory instanceof SessionFactoryImpl) {
SessionFactoryImpl sf = (SessionFactoryImpl)factory;
ConnectionProvider conn = sf.getConnectionProvider();
if(conn instanceof C3P0ConnectionProvider) {
((C3P0ConnectionProvider)conn).close();
try {
Thread.sleep(2000); //Let give it time...it is enough...probably
} catch (InterruptedException e) {
e.printStackTrace();
}
done = true;
}
factory.close();
}
return done;
}
You have to reference the hibernate-c3p0-4.x.x jar.
I'm very new to Hibernate and just wanted to query the initial basics.
I've created my Hibernate bean as such...
package com.behaviour.chapter1;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class User {
private int userId;
private String firstName;
#Id
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
I've configured my hibernate.cfg.xml and db connection there. My question is simply, how do I actually call this from a main method and use it in Hibernate3.6.6? I was following a tutorial online but it was for Hibernate3.2 and it seems to be a bit different. If anyone could show me just a really simple main method calling this bean, creating a new user (that would create a user in this table) it would be greatly appreciated. Also - if anyone has any good Hibernate tutorial links that would be great :)
Thanks,
There are several ways of doing this, it is a matter of design choice, a basic way to achieve this will be to create the session factory from hibernate.cfg.xml file. Make sure the file can be located at your classpath.
And using the class below, create a Session Factory object which is then used to open up new Session's
public class HibernateUtil
{
private static final SessionFactory sessionFactory;
static
{
try
{
// Create the SessionFactory from hibernate.cfg.xml
sessionFactory = new Configuration().configure().buildSessionFactory();
}
catch (Throwable ex)
{
// Make sure you log the exception, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory()
{
return sessionFactory;
}
}
Now to create a new user, do:
public class DaoFactory
{
public void create(Object obj)throws Exception
{
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
session.save(obj);
session.getTransaction().commit();
}
}
Main
public static void main(String[] args)
{
try
{
User user = new User();
user.setFirstName("david99world");
DaoFactory factory = new DaoFactory();
factory.create(user);
}
catch(Exception ex)
{
ex.printStackTrace(System.out);
}
}
EDIT
Your hibernate.cfg.xml should look something like this:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/test</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">none</property>
<mapping class="com.behaviour.chapter1.User"/>
</session-factory>
</hibernate-configuration>
I'm assuming you've set up your persistence.xml already. If so, you can use the following Java code. You'll have to substitute the "..." with your JDBC setup data and persistence unit.
private static final String PERSISTENCE_UNIT = "...";
final Map<String, String> properties = new HashMap<String, String>();
properties.put("javax.persistence.jdbc.driver", "...");
properties.put("javax.persistence.jdbc.url", "...");
properties.put("javax.persistence.jdbc.user", "...");
properties.put("javax.persistence.jdbc.password", "...");
final EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT, properties);
final EntityManager em = emf.createEntityManager();
User user = new User();
user.setUserID(0);
user.setFirstName("David");
em.getTransaction().begin();
em.persist(user);
em.getTransaction().commit();
HTH
Raku
Hibernate tutorials
Hibernate tutorial-1
Hibernate tutorial -2
Do you need a Session object to access the persistence unit. These objects are provided by SessionFactory objects.
Check the Hibernate reference guide.