So I'm trying to use Spring to manage hibernate transactions for the first time, and something's going wrong. I'm not sure what. I've looked at a bunch of similar answers on this site and nothing I've seen seems to be right.
So, I'm gonna copy and paste a bunch of my code with some explanations and ask for help here.
Here is a stack trace of the exception I'm getting. Essentially, It seems that it's trying to find org.hibernate.engine.transaction.spi.transactioncontext, and can't.
Exception stack trace
EXCEPTION: Could not open Hibernate Session for transaction; nested exception is java.lang.NoClassDefFoundError: org/hibernate/engine/transaction/spi/TransactionContext
org.springframework.orm.hibernate4.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:544)
org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:427)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:276)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
com.sun.proxy.$Proxy42.getSavedPortfolios(Unknown Source)
io.craigmiller160.stockmarket.controller.StockMarketController.showOpenPortfolioDialog(StockMarketController.java:994)
io.craigmiller160.stockmarket.controller.StockMarketController.parseEvent(StockMarketController.java:431)
io.craigmiller160.stockmarket.controller.StockMarketController.processEvent(StockMarketController.java:336)
io.craigmiller160.mvp.concurrent.AbstractConcurrentListenerController$1.run(AbstractConcurrentListenerController.java:209)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
Now, I've searched this site, and the big thing I saw was that this means I have a dependency wrong in my pom.xml. The thing is, I have the most up-to-date version of the hibernate-core dependency in my pom. From what I've read, that's what I need for this class.
pom.xml dependencies
<dependencies>
<!-- JUnit Testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- MVP Framework -->
<dependency>
<groupId>io.craigmiller160.mvp</groupId>
<artifactId>mvp-framework</artifactId>
<version>2.1.1</version>
</dependency>
<!-- MigLayout -->
<dependency>
<groupId>com.miglayout</groupId>
<artifactId>miglayout-swing</artifactId>
<version>5.0</version>
</dependency>
<!-- JFreeChart -->
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.0.19</version>
</dependency>
<!-- Java Concurrency In Practice Annotations -->
<dependency>
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<version>1.0</version>
</dependency>
<!-- Joda Time -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.8.2</version>
</dependency>
<!-- MySQL ConnectorJ -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.36</version>
</dependency>
<!-- Spring Framework Core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring Framework Beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring Framework Context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Hibernate Core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.0.1.Final</version>
</dependency>
<!-- XML Framework -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<!-- Code Generation library -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency>
<!-- Apache Commons Logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!-- LOG4J API -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>
<!-- LOG4J Core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
<!-- SLF4J/LOG4J Binding -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j.version}</version>
</dependency>
<!-- LOG4J/Commons Logging Binding -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jcl</artifactId>
<version>${log4j.version}</version>
</dependency>
<!-- SLF4J API -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.12</version>
</dependency>
<!-- Spring ORM -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- AspectJ Runtime -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<!-- AspectJ Weaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
<!-- Apache Database Connection Pooling -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
</dependencies>
Also, I'm adding the actual method in my DAO that I'm calling. This method is what is attempting to run when the exception is thrown.
DAO method:
@Transactional
@Override
@SuppressWarnings("unchecked") //hibernate list() method doesn't support generics
public List<String> getSavedPortfolios() throws HibernateException {
List<String> portfolioNames = new ArrayList<>();
List<SQLPortfolioModel> portfolioList = sessionFactory.getCurrentSession()
.createCriteria(PortfolioModel.class)
.list();
for(SQLPortfolioModel portfolio : portfolioList){
int id = portfolio.getUserID();
String name = portfolio.getPortfolioName();
BigDecimal netWorth = portfolio.getNetWorth();
Calendar timestamp = portfolio.getTimestamp();
String fileName = String.format("%1$d-%2$s-%3$s-"
+"%4$s", id, name, moneyFormat.format(netWorth),
timestampFormat.format(timestamp.getTime()));
portfolioNames.add(fileName);
}
return portfolioNames;
}
Lastly, here is my spring-context-data.xml. It contains all the configuration for my data beans for spring, plus the transaction stuff:
spring-context-data.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- Sets annotation-driven transactions -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- DataSource object for providing database connections -->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/stockmarket"/>
<property name="username" value="stockmarket"/>
<property name="password" value="stockmarket"/>
</bean>
<!-- SessionFactory object for creating sessions for database access -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- <property name="configLocation" value="classpath:hibernate.cfg.xml"/>-->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="connection.pool_size">1</prop>
<prop key="show_sql">false</prop>
<!-- Might need this one below for transactions, not sure yet -->
<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>io.craigmiller160.stockmarket.stock.AbstractStock</value>
<value>io.craigmiller160.stockmarket.stock.OwnedStock</value>
<value>io.craigmiller160.stockmarket.stock.DefaultStock</value>
<value>io.craigmiller160.stockmarket.stock.DefaultOwnedStock</value>
<value>io.craigmiller160.stockmarket.model.PortfolioModel</value>
<value>io.craigmiller160.stockmarket.model.SQLPortfolioModel</value>
</list>
</property>
</bean>
<!-- Hibernate Transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- HibernateDAO class for performing database operations -->
<bean id="hibernateDao" class="io.craigmiller160.stockmarket.controller.HibernatePortfolioDAO"
destroy-method="closeFactory">
<constructor-arg ref="sessionFactory"/>
</bean>
</beans>
So I just have no idea why this is happening. I've double and triple checked what I did versus what I'm seeing online, and I can't see the mistake. This is my first time trying to use Spring transaction management. Any help would be greatly appreciated.
PS. I'm using Spring 4 & Hibernate 5 together, if that makes a difference.
LocalSessionFactoryBean
or switch to hibernate4 – Ela