Spring disable transaction for method in transactional class

Overview

In Spring @Transactional  annotation can be used to indicate method should be run in transaction.

When @Transactional  is placed on method, this method will be run with transaction. And if it’s placed on a class, all methods of this class will run within transaction.

 

In MVC style application, we usually wrap business logic into a separate service class annotated with @Service  and @Transactional , so every method in this class will run within transaction. But how to disable transaction management for a specific single method in class which is annotated with @Transactional ?

 

Solution

Add following code before the method which you want to disable transaction management for.

Above code will tell Spring PlatformTransactionManager that transaction is not supported for this method, and transaction manager won’t create a new transaction if no transaction is existed.

And if a current transaction existed, exception will be thrown (An IllegalTransactionStateException with message “Existing transaction found for transaction marked with propagation ‘never'”).

 

java.lang.NoClassDefFoundError: java/util/Base64

Problem

In the following code, Base64 is used to encode AES encrypted data bytes to plain text for transfering via URL query parameter.

 

But when running this code on my coworker’s machine, following exception is thrown

 

It’s because that my execution environment is Java 8, but my coworker is using Java 7, and java.util.Base64 is introduced in Java 8.

 

Solution

To fix this issue, we can use Base64 class from Apache Commons Codec.

First add commons codec dependency to maven pom.xml file.

Next import Base64 class from commons-codec

 

Finally replace  Base64.getUrlEncoder().encodeToString to Base64.encodeBase64URLSafeString .

So the code will become like following

 

 

Method.invoke throws java.lang.IllegalArgumentException: wrong number of arguments

Background

There is a private downloadFile method of ZhangyoobaoLeshuaMerchantRegister class, the method signature is like following

A unit test case for this method need be created, in this test case we need pass a null value as parameter to test whether this method can handle null parameter. But a private method cannot be accessed from the instance level. The solution is to use reflection to get the method, and set its accessiblity to public temporarily (by using the Method.setAccessible method).

 

First let’s see some code

Above Java code is the unit test case, it uses reflection to get the private method downloadFile of class ZhangyoobaoLeshuaMerchantRegister, and set the access level of this method to public, then call it with parameters. (Note that if setAccessible is not called to set method access level, Method.invoke will throw IllegalAccessException.)

But running this line  result = method.invoke(register, null);  will got following error

It’s because the second argument of Method.invoke() is Object...  (An Object[] array), its elements are arguments passed in to the method. Calling Method.invoke() with null as second argument is actually trying to call the method with no arguments, but downloadFile method requires one parameter, so it definitely raises IllegalArgumentException.

 

Solution

To fix this issue, change following line

to

This will pass null as first argument for downloadFile method. new Object[]{null}  is correspondding to the Object...  argument of Method.invoke(), it’s expanded like calling downloadFile(null) .