Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring transactions not working + JAX WS + JDBC

I'm a bit exasperated with this issue. Lets check if someone has implemented something similar.

I have a java 8 web application with 8 WS implemented. Some of this WS, make inserts and updates through JDBCTemplate (Hibernate is not a choice due to performance needs) and i need them to rollback if execution crashes with an exception.

I have the following configuration of datasource and transaction manager in spring app context file (jndi resource in server.xml/context.xml of Tomcat):

  <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/jdbc/source" />
  </bean>
  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
  </bean>

  <tx:annotation-driven transaction-manager="transactionManager" />

On the other hand I have a unique accesspoint to the dataBase DBcontroller.class, which has a generic method for inserts, deletes and updates:

private NamedParameterJdbcTemplate jdbcTemplate;
private DataSource datasource;

@Autowired
public void setDataSource(DataSource dataSource) {
    this.datasource = dataSource;
    this.jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}
@Override
public boolean queryForModifying(String query, SqlParameterSource parameters) {

  int modifiedRows= 0;
  try {
      modifiedRows= this.jdbcTemplate.update(query, parameters);
  } catch (Exception e) {
      e.printStackTrace();
      numRegistrosAfectados = 0;
  }
  return (modifiedRows> 0) ? true : false;
}

Finally I have a WS Interface This way:

@WebService
public interface IService{

    @WebMethod
    public method(MethodRequestType request) throws IllegalArgumentException, IllegalAccessException;

}

with its implementation:

@WebService(endpointInterface = "com.package.IService")
@HandlerChain(file = "handler-chain.xml")
public class Service implements IService{

    @Autowired
    IDBController dbController;

with a "transactional" method:

@Transactional
private boolean inserts(HashMap<String, Object> input, MethodRequestType request) {.....

It should be working ok on a non WS project, but as I have discovered there is no so easy way for making this work.

First I thought it didn't rollback, but now I'm quite sure it doesn't create transactions.

There are some similar post in stackoverflow, but none of them fix my problem. I have google it a lot, and the only way suggested is WS-AtomicTransactions, which I have never heard about.

I have try almost everything in XML configuration file, I have even tried to manage transactions programatically, but as it is a pool of connections I'm not able to set autocommit to false so that I can force rollbacks.

For if it is useful for anyone, I have soap handlers implemented for each WS, that look this way:

public class ServiceHandler implements SOAPHandler<SOAPMessageContext> {

    private SoapFaultHandler soapFaultHandler;

    @Override
    public boolean handleMessage(SOAPMessageContext context) {

        SOAPMessage message = context.getMessage();
        soapFaultHandler = new SoapFaultHandler(message);
        return SoapMessageHandler.handleMessage(context, "Service name", logger);
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        return soapFaultHandler.handleFault(context, logger, "ServiceName");

    }
    ...
}
like image 983
Oldskultxo Avatar asked Aug 02 '18 13:08

Oldskultxo


People also ask

Can I use @transactional with JdbcTemplate?

It loops through the list of people and, for each person, inserts that person into the BOOKINGS table by using the JdbcTemplate . This method is tagged with @Transactional , meaning that any failure causes the entire operation to roll back to its previous state and to re-throw the original exception.

How would you enable transactions in Spring?

Annotation Type EnableTransactionManagement. Enables Spring's annotation-driven transaction management capability, similar to the support found in Spring's <tx:*> XML namespace. To be used on @Configuration classes to configure traditional, imperative transaction management or reactive transaction management.

Does Spring @transactional lock table?

"@Transactional" as itself on any isolation level doesn't enabling any locking. To achieve locking behaviour you should use "@Lock" annotation or use " for update" in your query.

Do we need @transactional in spring boot?

If you're using Spring without Spring Boot, you need to activate the transaction management by annotating your application class with @EnableTransactionManagement. Here you can see a simple example of a service with a transactional method.


1 Answers

It matters where you call the method annotated with @Transactional. For example if you have:

@Service
public class Service1 {

    @Transactional
    public void method1() { ... }

    public void method2() {
        method1();
    }
}

@Service
public class Service2 {

    @Autowired
    private Service1 service1;

    public void method1() {
        service1.method1();
    }

    public void method2() {
        service1.method2();
    }
}
  • Calling service2.method2() will NOT create a transaction.
  • Calling service2.method1() will create one.

Because of the way Spring handles Proxies and AOP.

like image 166
Radu Sebastian LAZIN Avatar answered Oct 03 '22 01:10

Radu Sebastian LAZIN