I am in the process of migrating a JBoss web application to Tomcat. During that migration I shifted to using Spring to configure Hibernate Session Factories and their respective data sources. When I began trying to hit the databases it complained about transactions, so I added declarative transaction management.
The problem I am having is that transaction management is working for one data source and not the other. Originally I thought the problem had to do with multiple data source / session factory / transaction manager groups; but removing all but the problematic group still didn't work.
The only thing unique about the data source which doesn't work is that it is a SQL Server "table view". In JBoss, the data source was configured as a no-tx-datasource but then still referred to the TransactionManager service:
<session-factory name="java:/hibernate/HibernateLoggingFactory" bean="jboss.har:service=HibernateLogging">
<property name="datasourceName">java:/LoggingDS</property>
<property name="dialect">org.hibernate.dialect.SQLServerDialect</property>
<property name="hibernate.default_schema">dbo</property>
<depends>jboss:service=Naming</depends>
<depends>jboss:service=TransactionManager</depends>
</session-factory>
Is the fact that I am trying to read a SQL Server 'table view' the source of my problem? I believe this to be the case because the exact same declarative transaction configuration otherwise works for my other data sources (which are not table views). Note that I can read the database just fine if I manually do session.beginTransaction() and session.getTransaction().commit(); the powers-that-be prefer the declarative approach and I have been stuck on this few a while now.
Code / Configuration:
Versions:
JDK 7u71
Maven 3.0.5
Tomcat 8.0.18
Spring 4.1.5.RELEASE
Hibernate 4.2.18.Final
CXF 3.0.4
Hibernate JPA API 2.0 1.0.1.Final
asm 3.1
cglib-nodep 2.2.2
JTDS 1.3.1
Spring autowiring is used to wire an exposed web service to a workflow to the dao.
DAO:
@org.springframework.stereotype.Repository("LogMessageViewDAO")
@EnableTransactionManagement
@Transactional(
value="LogAdminTxManager",
isolation=Isolation.READ_UNCOMMITTED,
readOnly=true)
public class LogMessageViewDAOImpl extends LogMessageViewDAO { ... }
Workflow (invoked by web service, invokes DAO):
@org.springframework.stereotype.Service("LogAdminWorkflow")
public class LogAdminWorkflow {
@Autowired LogMessageViewDAOImpl LogMessageViewDAO;
public void setLogMessageViewDAO(LogMessageViewDAOImpl logMessageViewDAO) {
LogMessageViewDAO = logMessageViewDAO;
}
...
}
CXF-Based Web Service (invokes workflow):
@WebService(
endpointInterface="x.y.z.session.LogAdministrationIF",
portName="LogAdministrationIFPort",
serviceName="LogAdministrationIFService")
public class LogAdministrationBean implements LogAdministrationIF {
@Autowired LogAdminWorkflow LogAdminWorkflow;
public void setLogAdminWorkflow(LogAdminWorkflow logAdminWorkflow) {
LogAdminWorkflow = logAdminWorkflow;
}
...
}
Spring context file:
<context:annotation-config />
<!-- DAOs -->
<context:component-scan base-package="x.y.z.dao" />
<!-- Workflows -->
<context:component-scan base-package="x.y.z.workflow" />
<!-- SOAP Web Services -->
<jaxws:endpoint id="LogAdministrationWS"
address="/logAdministration">
<jaxws:implementor>
<bean class="x.y.z.session.LogAdministrationBean"></bean>
</jaxws:implementor>
</jaxws:endpoint>
<!-- Data Sources -->
<bean id="logadminDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:/comp/env/jdbc/FastAdminLoggingDS" />
<property name="lookupOnStartup" value="true" />
<property name="proxyInterface" value="javax.sql.DataSource" />
</bean>
<!-- Session Factory -->
<bean
id="HibernateLogAdminFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
</props>
</property>
<!-- Scan Entities -->
<property name="packagesToScan" value="x.y.z.dao.logadmin" />
<property name="dataSource">
<ref bean="logadminDataSource" />
</property>
</bean>
<!-- Transaction Manager -->
<bean id="LogAdminTxManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="dataSource" ref="logadminDataSource" />
<property name="sessionFactory" ref="HibernateLogAdminFactory" />
<qualifier value="LogAdminTxManager"/>
</bean>
<tx:annotation-driven transaction-manager="LogAdminTxManager" />
The data source is defined by my Tomcat server, so I have a ResourceLink to it in the web application's context.xml:
<ResourceLink
name="jdbc/FastAdminLoggingDS"
global="jdbc/FastAdminLoggingDS"
auth="Container" type="javax.sql.DataSource" />
Aucun commentaire:
Enregistrer un commentaire