I'm new with Spring and I'm trying to configure it by using the transaction manager of jboss. Indeed, i receive this exception:
Caused by: org.hibernate.resource.transaction.backend.jta.internal.JtaPlatformInaccessibleException: Unable to access TransactionManager or UserTransaction to make physical transaction delegate
This is my config.xml:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:jboss/datasources/mydb"/>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="ufirst" />
</bean>
<bean id="txManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="java:jboss/TransactionManager" />
<property name="userTransactionName" value="java:jboss/UserTransaction" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />
<tx:jta-transaction-manager />
And this is my repository, that return the error:
#Repository
#Transactional(readOnly = true)
public class RoleRepositoryimpl implements RoleRepository {
private static final Logger logger = LoggerFactory.getLogger(RoleRepositoryJpa.class);
#PersistenceContext(unitName="entityManagerFactory")
private EntityManager em;
#Transactional
public Role find(String role){
logger.info("in repository");
return em.find(Role.class, role);
}
Thanks in advance for your reply.
Related
Im using JPA with Hibernate implementation and using JpaTransactionManager to mange transactions.
Below is my application context file
<bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>classpath*:META-INF/persistence.xml</value>
</list>
</property>
<property name="defaultDataSource" ref="dataSource" />
</bean>
<bean id="entityManagerFactory" primary="true"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="persistenceUnitName" value="infra_services" />
</bean>
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
I have defined my service class as below
#Service
#Transactional
public class ComponentService {
I execute queries in dao layer as below
Query q = entityManager.createQuery(
"SELECT cc.component FROM "
+ this.typeParameterClass.getSimpleName()
+ " cc WHERE cc.caseload.id = ? ").setParameter(1,
caseloadId);
Collection<Component> ddd =q.getResultList();
for (Component c : ddd) {
System.out.println(c.getComponentId());
System.out.println(c.getComponentRelationships2());
}
return ddd;
I started with select queries. While executing the line System.out.println(c.getComponentRelationships2()); getting could not initialize proxy - no Session] with root cause exception
Not sure why the session is not available here. Please help me on this.
If your service is not in the same context as the one where <tx:annotation-driven /> then it's not working. Because it only look for bean in the same context. Extract from spring doc:
#EnableTransactionManagement and only looks for #Transactional on beans in the same application context they are defined in. This means that, if you put annotation driven configuration in a WebApplicationContext for a DispatcherServlet, it only checks for #Transactional beans in your controllers, and not your services. See Section 21.2, “The DispatcherServlet” for more information.
I have an existing code which is written using Spring + Hibernate session factory. I have DAOs written using sessionFactory which are transactional.
#Transactional
public class WorkingDAO<T> {
private SessionFactory sessionFactory;
public void save(T t){
sessionFactory.getCurrentSession().save(t);
}
}
I have unit tests which tests for this DAO which were working fine. Now i want to use Spring JPA so to reduce the effort of writing DAO classes. So I used the following configuration
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
<property name="jpaDialect" ref="jpaDialect"/>
<property name="jpaProperties">
....
</bean>
<bean id="SessionFactory" factory-bean="entityManagerFactory"
factory-method="getSessionFactory" />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven/>
However my older unit tests are failing after using the above configuration. Can i use the existing SessionFactory ? or do i have to migrate to the entityManager ?
I have been facing the below error while trying to save the object to database. I tried the solution mentioned here1 and here2 but no good. I was following a tutorial but the only difference is versions of Spring and Hibernate.
I am able to persist the object directly using the SessionFactory but it fails with below error if I try this with HibernateDaoSupport
spring.xml
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#localhost:1521:xe" />
<property name="username" value="system" />
<property name="password" value="xxx" />
</bean>
<context:annotation-config/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="packagesToScan" value="org.sri.sphiber.model"></property>
<property name="hibernateProperties">
<props>
<prop key="dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="customerDAOImpl" class="org.sri.sphiber.dao.CustomerDAOImpl">
<property name="hibernateTemplate" ref="hibernateTemplate" />
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
CustomerDAOImpl.java
public class CustomerDAOImpl extends HibernateDaoSupport {
public boolean insertCustomer(Customer cust){
try {
getHibernateTemplate().saveOrUpdate(cust);
} catch (DataAccessException e) {
e.printStackTrace();
return false;
}
return true;
}
}
Invoke it using.
public class MainClass {
public static void main(String[] args) {
ApplicationContext appContext = new ClassPathXmlApplicationContext("spring.xml");
CustomerDAOImpl hdi=appContext.getBean("customerDAOImpl",CustomerDAOImpl.class);
Customer customer=new Customer();
customer.setCustomerName("Sri");
boolean isUpdated = hdi.insertCustomer(customer);
}
}
Error message.
Aug 10, 2014 12:45:52 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000232: Schema update complete
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
at org.springframework.orm.hibernate4.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1135)
at org.springframework.orm.hibernate4.HibernateTemplate$16.doInHibernate(HibernateTemplate.java:684)
at org.springframework.orm.hibernate4.HibernateTemplate.doExecute(HibernateTemplate.java:340)
at org.springframework.orm.hibernate4.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:308)
at org.springframework.orm.hibernate4.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:681)
at org.sri.sphiber.dao.CustomerDAOImpl.insertCustomer(CustomerDAOImpl.java:16)
at org.sri.sphiber.main.MainClass.main(MainClass.java:26)
Version Details :
Spring version : spring-framework-4.0.6.RELEASE
Hibernate Version : hibernate-release-4.3.5.Final
Database : Orcale 11g
You are missing TransactionManager definition, see http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/transaction.html
[UPDATE]
Previously i was writing from my mobile so it was hard to provide details, here is what you need to do:
Spring xml config:
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Add #Transactional annotation to CustomerDaoImpl.insertCustomer method
Now your code should work.
Please note that #Transactional annotation should be used in service layer, not in DAO layer like in this example.
#Transactional annotation tells spring to create proxy which "wraps" annotated method with transaction using aspects.
In configuration file
do the change:-
#Configuration
#EnableTransactionManagement <-----Put this line
public PersistenceConfig{
//your code
}
(OR)
#Bean
#Autowired
public HibernateTemplate getHibernateTemplate(SessionFactory session) {
HibernateTemplate hb = new HibernateTemplate();
hb.setCheckWriteOperations(false);
hb.setSessionFactory(session);
return hb;
}
I have a problem with my #Transactional method. After this method executed - the new record inserted into table and no rollback happens on exception
#RestController
#RequestMapping("/rest")
public class TestController {
#Autowired
private TestMapper testMapper;
#Transactional
#RequestMapping("/test")
String test() {
TestObj obj = new TestObj();
obj.setName(new Date().toString());
testMapper.insert(obj);
int i = 1 / 0; // doing exception
return obj.toString();
}
}
My xml configurations:
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/test"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.test.mapper"/>
</bean>
Am i missing something? I just want DB to stay unchanged if some exception happens in my method
EDIT:
The problem was that method was not defined as public
Just throw new RuntimeException and change your annotation to #Transactional(rollbackFor=Exception.class).
We had this kind of problem, here is the conf we use it may help you. Note that we are relying on the ApplicationServer:
<!-- Initialize MyBatis Session Factory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- Plug datasource and mapperLocations -->
<property name="dataSource" ref="dataSource" />
<property name="transactionFactory">
<bean
class="org.apache.ibatis.transaction.managed.ManagedTransactionFactory" />
</property>
</bean>
I am new to Spring framework; need some clarifications on how the SessionFactory object Dependency injection is working in below code.
spring-servlet.xml
<context:annotation-config />
<context:component-scan base-package="com.employee" />
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/jdbc.properties" />
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}" p:username="${jdbc.username}"
p:password="${jdbc.password}" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:employee.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
EmployeeDAOImpl.java
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
#Repository
public class EmployeeDAOImpl implements EmployeeDAO {
#Autowired
private SessionFactory sessionFactory;
#Override
public void addEmployee(EmployeeForm employee) {
sessionFactory.getCurrentSession().save(employee);
}
}
How is the sessionFactory getting initialized with a SessionFactory object here?
What I understand
In the sprng-servlet.xml file, the DI of sessionFactory is happening in the below code:
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Now, if I open the source code for the class org.springframework.orm.hibernate3.HibernateTransactionManager, then I can see the below section:
private SessionFactory sessionFactory;
public HibernateTransactionManager(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
afterPropertiesSet();
}
public void setSessionFactory(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
public SessionFactory getSessionFactory(){
return this.sessionFactory;
}
which means the sessionFactory class variable of org.springframework.orm.hibernate3.HibernateTransactionManager has been initializd.
Now my Query:
In my code posted above, how is the sessionFactory of class EmployeeDAOImpl.java getting initialized? I can't find any relation between the sessionFactory of class org.springframework.orm.hibernate3.HibernateTransactionManager (where DI is happening) and the sessionFactory of class EmployeeDAOImpl.java (which I wrote). Then how is it working?
Please explain - totally confused !!!
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:employee.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
You have defined the session factory bean in you context file. During the application bootstrap, the spring context is loaded and this session factory bean is initialized by spring as a singleton instance.
<context:annotation-config />
<context:component-scan base-package="com.employee" />
#Autowired
private SessionFactory sessionFactory;
And since you have enabled the annotation-config and component-scan and declared #Autowired in your DAOImp, this is the reason Spring knows the place to inject the session factory bean properly.
This configuration is enabled the transaction manager annotation.
Example:
#Transactional
public void addEmployee(EmployeeForm employee){...}
Here is the suggestion.
Transactional annotation is better to be placed in service layer instead of DAO layer. You need to make sure the annotation is placed on the concrete class unless you use the interface-proxy in your component-scan.
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
This piece of configuration is set the transaction manager bean which lets transaction manager knows which session factory it needs to manage with.
Therefore the configuration of bean
id="transactionManager" sets the transaction manager with the proper hibernate session factory.
tx:annotation-driven configuration enables the annotation-based transaction manager in code level.
Hope the explanation is helpful for you. :)