JTATransactionManager Not Committing To Database - spring

I will be working with a database and with a JMS queue so I decided to use JTATransactionManager (multiple resources).
I am using Spring Framework 3.2.3.RELEASE
Hibernate 4.2.1.Final
Glassfish 3.1.2.2
With JTATransactionManager nothing is committed to db.I tried JPATransactionManager it works fine.I don't get any exceptions with JTATransactionManager.Any idea what I am doing wrong?Thanks.
This is a piece of jpa config file
<jee:jndi-lookup id="dataSource" jndi-name="Test" />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:packagesToScan="com.pinkshield.jpaTest.domain"
p:dataSource-ref="dataSource"
p:jpaPropertyMap-ref="jpaPropertyMap"
p:jpaVendorAdapter-ref="hibernateVendor" />
<util:map id="jpaPropertyMap">
<entry key="hibernate.hbm2ddl.auto" value="validate" />
<entry key="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect" />
<entry key="transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory" />
<entry key="transaction.manager_lookup_class"
value="org.hibernate.transaction.SunONETransactionManagerLookup" />
</util:map>
<bean id="hibernateVendor"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
p:showSql="true" />
<tx:jta-transaction-manager />
<context:component-scan base-package="com.pinkshield.jpaTest" />
This is my Generic Dao for JPA
package com.pinkshield.jpaTest;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
public class GenericDaoJpa<T> implements GenericDao<T>
{
private Class<T> queryClass;
protected EntityManager entityManager;
#PersistenceContext
public void setEntityManager(EntityManager entityManager)
{
this.entityManager = entityManager;
}
public GenericDaoJpa(Class<T> queryClass)
{
super();
this.queryClass = queryClass;
}
public T getNewInstance()
{
try
{
return getQueryClass().newInstance();
}
catch (InstantiationException e)
{
throw new RuntimeException("Error creating new instance of : " + getQueryClass().getName(), e);
}
catch (IllegalAccessException e)
{
throw new RuntimeException("Error creating new instance of : " + getQueryClass().getName(), e);
}
}
public Class<T> getQueryClass()
{
return queryClass;
}
public T get(Long id)
{
if (id == null)
{
return null;
}
else
{
return entityManager.find(queryClass, id);
}
}
#SuppressWarnings("unchecked")
public List<T> getAll()
{
return entityManager.createQuery("select o from " + queryClass.getName() + " o").getResultList();
}
public void save(T object)
{
entityManager.persist(object);
}
public void update(T object)
{
entityManager.merge(object);
}
public void delete(T object)
{
entityManager.remove(entityManager.merge(object));
}
}
This is UserDao
#Repository
public class UserDao extends GenericDaoJpa<User>
{
public UserDao()
{
super(User.class);
}
}
And this is my service code
#Service
public class UserServiceImpl implements IUserService{
#Autowired UserDao userDao;
#Override
#Transactional
public void saveUser(String name, String lastName)
{
User user=new User();
user.setLastName(lastName);
user.setName(name);
userDao.save(user);
}
}

I think you need to add <tx:annotation-driven/> to the context xml. That will run a context post processor that will wrap methods with #Transactional with an AOP method interceptor that provides the transaction behavior you're looking for.

Related

Spring not roll back transaction if exception throws in the application

I developed the application using spring transactions and insert records in the table.
I'm explicitly throwing the exception in DAO class but spring is inserting the record into the table rather than roll back the transaction.
I have created the two applications as below . In Case 1 record is inserted into table even though exception is thrown . But In Case 2 no record is inserted and spring roll back the transaction successfully. Can you explain me the difference between these two applications.
Case 1:
Item.java
public class Item {
int itemNo;
String itemName;
String itemType;
String itemSize;
public int getItemNo() {
return itemNo;
}
public void setItemNo(int itemNo) {
this.itemNo = itemNo;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public String getItemType() {
return itemType;
}
public void setItemType(String itemType) {
this.itemType = itemType;
}
public String getItemSize() {
return itemSize;
}
public void setItemSize(String itemSize) {
this.itemSize = itemSize;
}
}
ItemDao
#Service
public class ItemDao {
#Autowired
JdbcTemplate jdbcTemplate ;
void insert(Item item){
jdbcTemplate.update("insert into item_test(itemno, itemtype,itemsize,itemname) values (?,?,?,?)", new Object[]{item.getItemNo(),item.getItemType(),item.getItemSize(),item.getItemName()});
int a=2/0;
}
}
ItemService.java
#Service
public class ItemService {
#Autowired
ItemDao itemDao;
#Transactional
public void insert(Item item){
try{
itemDao.insert(item);
}
catch(Exception e){
e.printStackTrace();
}
}
}
Test.java
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext ct = new ClassPathXmlApplicationContext("spring.xml");
ItemService itemService = ct.getBean("itemService", ItemService.class);
Item item = new Item();
item.setItemNo(1234);
item.setItemName("sofa");
item.setItemSize("4");
item.setItemType("furniture");
itemService.insert(item);
}
}
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- Enable Annotation based Declarative Transaction Management -->
<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />
<context:component-scan base-package="com.spring.springtransaction" />
<!-- Creating TransactionManager Bean, since JDBC we are creating of type
DataSourceTransactionManager -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- MySQL DB DataSource -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#locahost:1521:xe)))" />
<property name="username" value="system" />
<property name="password" value="system" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="itemService" class="com.spring.springtransaction.ItemService" />
</beans>
Case 2:
ItemService.java
#Service
public class ItemService {
#Autowired
ItemDao itemDao;
#Autowired
ItemManger itemManger;
#Transactional
public void insert(Item item){
try{
itemManger.insert(item);
}
catch(Exception e){
e.printStackTrace();
}
}
}
ItemManger.java
#Service
public class ItemManger {
#Autowired
ItemDao itemDao;
#Transactional
public void insert(Item item){
itemDao.insert(item);
}
}
ItemDao.java
#Service
public class ItemDao {
#Autowired
JdbcTemplate jdbcTemplate ;
void insert(Item item){
jdbcTemplate.update("insert into item_test(itemno, itemtype,itemsize,itemname) values (?,?,?,?)", new Object[]{item.getItemNo(),item.getItemType(),item.getItemSize(),item.getItemName()});
int a=2/0;
}
}
Annotate you ItemDao as #Repository instead of #Service
You should execute unit test with spring Transactional context instead of main , for example using TestNG:
#ContextConfiguration(classes = {ConfigurationClass.class})
#ActiveProfiles({"test"})
public class TestItemDAO extends AbstractTransactionalTestNGSpringContextTests {
#Autowired
private ItemDao dao;
#Test
public void testItemDao() {
dao.insert(item);
}
}
Remove the try block, you are trying to handle the exception so this is reason why RollbackException is not cutting the transaction stream.

Why my DAO classes are not scanned?

I've been stuck for a week with this problem and there is no way to find a solution in my project using Spring tool suite.
My dispatcher scan packages and creates beans for the controller and service layer but it seems it can't reach the model layer.
This is my servlet-context.xml:
<beans:bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<!-- <beans:property name="dataSource" ref="dataSource"/> -->
<beans:property name="configLocation" value="classpath:hibernate-annotation.cfg.xml" />
</beans:bean>
<tx:annotation-driven/>
<!-- <beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="sessionFactory" />
</beans:bean> -->
I have commented the transactionManager bean because it throws an expection.
The problem comes up when in my UserServiceImpl set UserDaoI as #Autowired
#Service
public class UserServiceImpl implements UserServiceI{
private static final Logger logger =
Logger.getLogger(UserServiceImpl.class);
#Autowired
UserDaoI userDao;
public boolean isRegisteredUser(User user){
logger.debug("Entrando en isRegisteredUser" + logger.getClass());
boolean isRegistered = false;
UserDao uDao = userDao.getUserByDni(user.getDni());
if(!(uDao.getEmail().equals(user.getEmail()))){
isRegistered = true;
}
return isRegistered;
}
I am clueless and desperate.
EDIT:
This is my UserDaoI class, but I think is not relevant.
public interface UserDaoI {
void addUser(UserDao userDao);
UserDao getUser(int id);
boolean updateUser(UserDao userDao);
boolean deleteUser(int id);
List<UserDao> getAllUsers();
UserDao getUserByDni(String dni);
}
This is my UserDaoImpl.java, the source of the problems.
#Repository
public class UserDaoImpl implements UserDaoI{
private static final Logger logger = LoggerFactory.getLogger(UserDaoImpl.class);
#Autowired
SessionFactory sessionFactory;
Session session;
#Override
public void addUser(UserDao userDao) {
session = sessionFactory.openSession();
session.beginTransaction();
session.save(userDao);
session.getTransaction().commit();
session.close();
}
#Override
public UserDao getUser(int id) {
//sessionFactory = HibernateUtil.getSessionFactory();
session = sessionFactory.openSession();
session.beginTransaction();
UserDao userDao = (UserDao) session.get(UserDao.class, id);
session.getTransaction().commit();
session.close();
return userDao;
}
#Override
public boolean updateUser(UserDao userDao) {
assert(userDao!=null);
//sessionFactory = HibernateUtil.getSessionFactory();
session = sessionFactory.openSession();
session.beginTransaction();
session.update(userDao);
session.getTransaction().commit();
session.close();
return false;
}
#Override
public boolean deleteUser(int id) {
//sessionFactory = HibernateUtil.getSessionFactory();
session = sessionFactory.getCurrentSession();
UserDao userDao = new UserDao();
userDao.setId(id);
if(getUser(id)!=null){
try{
session.beginTransaction();
session.delete(userDao);
session.getTransaction().commit();
return true;
}catch(Exception ex){
logger.error("No se ha podido borrar el usuario");
}finally{
session.close();
}
}
return false;
}
#Override
public List<UserDao> getAllUsers() {
//sessionFactory = HibernateUtil.getSessionFactory();
session = sessionFactory.openSession();
session.beginTransaction();
#SuppressWarnings("unchecked")ArrayList<UserDao> userDaoList = (ArrayList<UserDao>) session.createQuery("from user").list();
session.getTransaction().commit();
session.close();
return userDaoList;
}
#Override
public UserDao getUserByDni(String dni) {
session = sessionFactory.getCurrentSession();
session.beginTransaction();
UserDao userDao = (UserDao) session.createQuery("from user where dni = " + dni).uniqueResult();
session.getTransaction().commit();
session.close();
return userDao;
}
}
Why I do not need to autowire my Session?
This is my hibernate config
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/gen</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">fiw48asi</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="show_sql">true</property>
<mapping class="com.library.app.dao.user.UserDao"/>
</session-factory>
Now the exception I get is
org.hibernate.hql.internal.ast.QuerySyntaxException: user is not mapped
But it is declared in hibernate-annotation.cfg.xml
Thanks a ton!
The problem is:
'userDaoImpl': Injection of autowired dependencies failed...: Could not autowire field:
because
No qualifying bean of type [org.hibernate.SessionFactory] found for dependency: expected at least 1 bean which qualifies as autowire candidate
In your model, you will need to define a userDaoImpl bean with an #Bean annotation and a Hibernate SessionFactory to allow Spring to create and inject it, e.g.,: add a method to your UserServiceImpl class like this:
UserServiceImpl.java
#Bean
public UserDaoI userDao() {
return new UserDaoImpl();
}
But I notice some mixing of types and models, however, which I think is at the root of your issues, so I'll explain how the service with DAO model works generally with a simpler model.
In a "service and data access object" model, you create a persistence mediator for each entity, conventionally with a DAO suffix and the entity is typically a simple plain ordinary Java object (POJO).
For example, to represent an in-memory user, you might model the entity as follows:
User.java
public class User {
private String name;
// more POJO properties as need..
public void setName(String name) {
this.name = name;
}
public String getName(String name) {
return this.name;
}
// more POJO setters and getters...
}
Now we need a mediator which can create, read, update, and delete these entities from our database. In a DAO pattern, that's the role of the entity's DAO:
UserDao.java
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
public class UserDao {
#Autowired
private SessionFactory sessionFactory;
public User getUser(long id) {
sessionFactory.getCurrentSession().get(User.class, id);
}
public void addUser(User user) {
sessionFactory.getCurrentSession().saveOrUpdate(user);
}
//...
}
We add a service layer on top of the DAO layer when services either span entities or add some (likely to change) business logic to the entity. For example, supposed we have a registration table which captures registration records in various states for each user:
UserService.java
public class UserService {
#Autowired
private UserDao userDao
#Autowired
private RegistrationDao registrationDao
public boolean isRegistered(long userId) {
// DAOs mediate access to tables
User user = userDao.getUser(userId);
Registration reg = registrationDao.getRegistration();
//
// business logic
//
return isUserRegistered(user, registration);
}
}
With Spring 4, though, I don't hand-code my DAO layers anymore; instead I use Spring Data JPA with the Hibernate JPA provider. Here's a very simple example of how to make this work. You're already using the Hibernate ORM, so you don't "lose" much (quite the opposite, really) by using Spring Data JPA with the Hibernate JPA provider.

UsernameTokenValidator Can not #Autowired Dao

I have a Spring-ws and i am using Apahce-wss4j for spring-ws authentication. I want to use my Dao class in my custom TokenValidator class. But there was an exception can not #Autowired my Dao class. Here is my code
applicationContext.xml
<bean id="myWssConfig" class="tr.com.xxx.services.MyWssConfig"/>
<bean id="kepDBDAO" class="tr.com.xxx.dao.KepDBDAOImpl"/>
<bean id="ssha" class="tr.com.xxx.utils.SSHA"/>
<bean id="memberStatusService" class="tr.com.xxx.services.MemberStatusServiceImpl"/>
<bean id="myUsernameTokenValidator" class="tr.com.xxx.services.MyUsernameTokenValidator">
<property name="kepDBDAO" ref="kepDBDAO"/>
</bean>
<sws:interceptors>
<bean class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
<property name="validationActions" value="UsernameToken"/>
<property name="validationCallbackHandler" ref="callbackHandler"/>
<property name="wssConfig">
<ref bean="myWssConfig"/>
</property>
</bean>
</sws:interceptors>
Here is MyWssConfig.java
#Component("myWssConfig")
public class MyWssConfig extends WSSConfig {
public MyWssConfig() {
setValidator(WSSecurityEngine.USERNAME_TOKEN, MyUsernameTokenValidator.class);
setRequiredPasswordType(WSConstants.PASSWORD_TEXT);
}
}
And here is MyUsernameTokenValidator.java
#Component
public class MyUsernameTokenValidator extends UsernameTokenValidator {
private static final Logger LOGGER = LoggerFactory
.getLogger(MyUsernameTokenValidator.class);
#Autowired
private KepDBDAO kepDBDAO;
#Transactional
protected void verifyPlaintextPassword(UsernameToken usernameToken, RequestData data) throws WSSecurityException {
if (usernameToken != null && usernameToken.getPassword() != null) {
byte[] saltValue = null;
kepDBDAO.getWsUsers("basvuru");
String hashPassword = null;
try {
hashPassword = SSHA.calculateSSHA256(saltValue, usernameToken.getPassword());
} catch (NoSuchAlgorithmException e) {
LOGGER.error(e.toString(), e);
} catch (IOException e) {
LOGGER.error(e.toString(), e);
}
usernameToken.setPassword(hashPassword);
super.verifyDigestPassword(usernameToken, data);
}
}
public KepDBDAO getKepDBDAO() {
return kepDBDAO;
}
public void setKepDBDAO(KepDBDAO kepDBDAO) {
this.kepDBDAO = kepDBDAO;
}
}
Couldn't #Autowired my KepDBDAO when I call webservice in SOAPUI.
Help me please.. THank you all guys.
Try this:
1. In applicationContext:
<context:component-scan base-package="tr.com.xxx.dao"/>
<context:component-scan base-package="package for MyUsernameTokenValidator"/>
remove these beans:
kepDBDAO, myUsernameTokenValidator
2. Remove setter and getter for KepDBDAO in MyUsernameTokenValidator
3. Make sure KepDBDAOImpl is marked as #Service
I solved my problem.
#Component("myWssConfig")
public class MyWssConfig extends WSSConfig {
#Autowired
private MyUsernameTokenValidator myUsernameTokenValidator;
//
#PostConstruct
public void myInit() {
setValidator(WSSecurityEngine.USERNAME_TOKEN, myUsernameTokenValidator);
setRequiredPasswordType(WSConstants.PASSWORD_TEXT);
}
}

Spring data MongoDb cannot convert proxy bean

I'm using Spring AOP with AspectJ and Spring Data MongoDb and am having a world of trouble persisting objects.
In this case, I have an AclEntryDaoImpl that exposes AclEntryImpl. When AclEntryImpl is provided a Principal that is a standard Java object (a "non-Spring" bean), mongoTemplate.save() works as expected. However when Principal is a Spring bean, Mongo is unable to convert the object and results in a MappingException org.springframework.data.mapping.model.MappingException: No id property found on class class com.sun.proxy.$Proxy33. All my objects need to be Spring beans so that (a) I keep my objects decoupled and (b) my AOP (LoggingAspect) is invoked.
Lastly, I cannot take advantage of Spring converters because Mongo sees the target object AclEntryImpl as a proxy com.sun.proxy.$Proxy33 and so Converter<Principal, DBObject> is never invoked.
Any and all help would be greatly appreciated!
Snippets:
Here's my Spring XML configuration:
<beans>
<context:component-scan base-package="a.b" />
<context:property-placeholder location="config.properties" />
<aop:aspectj-autoproxy />
<bean id="loggingAspect" class="a.b.LoggingAspect" />
<mongo:db-factory host="${database.host}" port="${database.port}" dbname="${database.dbname}" />
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
</bean>
<bean id="aclEntryDao" class="a.b.AclEntryDaoImpl">
<lookup-method name="createAclEntry" bean="aclEntry" />
</bean>
</beans>
AclEntryImpl:
#Document
#Component
#Scope("prototype")
public class AclEntryImpl implements AclEntry {
#Id
private String id;
private String service;
#DBRef #Expose
private Principal principal;
#Expose
private boolean accessGranted;
#Expose
private List<Permission> permissions;
#Override #Loggable #MongoSaveReturned
public AclEntry save() {
return this;
}
...getters and setters...
}
AclEntryDaoImpl:
#Repository
public abstract class AclEntryDaoImpl implements AclEntryDao {
#Override #Loggable
public AclEntry addEntry(String serviceName, Principal principal, Permission[] permissions, boolean accessGranted) throws Exception {
AclEntry entry = createAclEntry(); //<-- Spring lookup-method
entry.setService(serviceName);
entry.setPrincipal(principal); //<-- com.sun.proxy.$Proxy33
entry.setAccessGranted(accessGranted);
for (Permission permission : permissions) {
if (!entry.addPermission(permission)) {
return null;
}
}
return entry.save();
}
... other DAO methods ...
}
LoggingAspect:
#Aspect
public class LoggingAspect {
#Autowired
private MongoTemplate mongoTemplate;
#Pointcut("execution(!void a.b..*.*(..))")
public void returningMethods() {}
#AfterReturning(pointcut="returningMethods() && #annotation(MongoSaveReturned)", returning="retVal")
public Object mongoSaveReturnedAdvice(Object retVal) {
Logger logger = null;
try {
logger = getLogger(retVal);
mongoTemplate.save(retVal); //<-- throws MappingException
log(logger, "save: " + retVal.toString());
} catch (Exception e) {
log(logger, "throw: " + e.toString());
}
return retVal;
}
... other logging methods ...
}

Spring not dynamic Switch DataSource

Why use AbstractRoutingDataSource can not dynamic switch DataSource
This is the configuration information
public class DynamicSwitch {
public static final ThreadLocal<String> local=new ThreadLocal<String>();
public static void setDB(String id){
local.set(id);
}
public static String getDB(){
return local.get();
}
public static void removeDB(){
local.remove();
}
}
public class DynamicSource extends AbstractRoutingDataSource implements InitializingBean{
#Override
protected Object determineCurrentLookupKey() {
// TODO Auto-generated method stub
return DynamicSwitch.getDB();
}
}
<bean id="dynamic" class="com.aware.DynamicSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="1" value-ref="dataSource"></entry>
<entry key="2" value-ref="localdataSource"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="dataSource"></property>
</bean>
<bean id="methodService" class="com.test.service.MethodServiceImpl">
<property name="sqlMapClient" ref="sqlMapClient"></property>
</bean>
<bean id="test" class="com.test.Test" scope="prototype"></bean>
public class Test2 extends ActionSupport{
public String execute() throws Exception {
// TODO Auto-generated method stub
DynamicSwitch.setDB("2");
MethodService methodService=(MethodService)ApplicationAware.getBean("methodService");
Map<String, String> map=new HashMap<String, String>();
List list=methodService.testList("Service_ks_missionSpace.getService_ks_missionList", map);
System.out.println(list.size());
return SUCCESS;
}
Invoke DynamicSwitch.setDB("2") find can not Switch DataSource.
DataSource or to default dataSource
Why

Resources