Why use `Propagation.REQUIRED` over `Propagation.NESTED`? - java

With Spring, by default transactions use Propogation.REQUIRED, but this seems like a rather odd choice to me. If we ignore the existence of transactions, then it's a very normal pattern to catch an exception, and implement a fallback. E.g. in it's very basic form:
public void doSomethingFirst() {}
public void doSomethingElse() {}
public void doSomethingWithFallback() {
this.doSomething();
try {
this.doSomethingElse();
} catch (Exception e) {
this.fallback();
}
}
However, Propagation.REQUIRED breaks this:
public void doSomethingFirst() { }
#Transactional(propagation = Propagation.REQUIRED)
public void doSomethingElse() { }
#Transactional(propagation = Propagation.REQUIRED)
public void doSomethingWithFallback() {
this.doSomethingFirst();
try {
this.doSomethingElse();
} catch (Exception e) {
this.fallback();
}
}
Now if doSomethingElse fails, it will mark the transaction as rollback only. Even though we have a perfectly fine fallback, the entire transaction will be rolled back and there's nothing we can do to stop this.
The "fix" for this is to use NESTED instead of REQUIRED (at least in the doSomethingElse):
public void doSomethingFirst() { }
#Transactional(propagation = Propagation.NESTED)
public void doSomethingElse() { }
#Transactional(propagation = Propagation.NESTED)
public void doSomethingWithFallback() {
this.doSomethingFirst();
try {
this.doSomethingElse();
} catch (Exception e) {
this.fallback();
}
}
Now, we're using savepoints, and if doSomethingElse fails it will only rollback doSomethingElse.
To me it looks like NESTED is the behaviour that we almost always want, and I'm struggling to come up with any use case where REQUIRED would be preferred. REQUIRED prohibits the caller from recovering from errors, which is normally a bad idea.
But given that REQUIRED is the default, and that NESTED is barely ever used, surely there must be some reason why we should use REQUIRED over NESTED.
In what cases should we prefer REQUIRED over NESTED?

Related

Execute same piece of code in catch clause for all methods in a class

I have a class that has many methods. All the methods throw one exception when data is not ready. In that case, I want to retry the method after a certain interval. So in catch, I need to add retry logic. The same logic i need to add for all methods.
Is there some way/pattern to execute same logic for all catch clause without copy paste
One way I could think of is to write my own Exception class and Throw that exception. And do this retry logic from My Exception class.
Is there any other better way to this?
class MyClass {
public void method1() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
public void method2() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
public void method3() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
}
EDIT:
class MyClass {
public void method1(int a, int b) {
try {
//do some logic
} catch (Exception e) {
Object args[] = {a,b};
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public void method2() {
try {
//do some logic
} catch (Exception e) {
Object args[] = null;
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public void method3(String abcd, int a) {
try {
//do some logic
} catch (Exception e) {
Object args[] = {abcd,a};
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public boolean executeLater(String methodName, Object args[]){
//Execute given method with the supplied args
return true;
}
}
Added code that shows what i would be doing in each catch clause
boolean processCompleted=false;
while(!processCompleted){
try{
doProcess();
processCompleted=true;
}catch(Exception e){
Thread.sleep(10000);
}
}
This might give you an idea. It keeps try to call doProcess until it doesn't throw exception. If any exception occurs, waits 10 seconds.
Well, you could extract the whole catch block content to a method and call that one, but this only works if your retry logic is not dependent on the specific method. And it also requires a try-catch in every method.
Instead, use functional programming to shorten it:
public class Playground
{
public static void main(String[] args)
{
new Playground().method2(1, 2);
new Playground().method1();
}
public void method1()
{
tryAndTryAgain(() -> {
// logic 1
System.out.println("no params");
throw new RuntimeException();
});
}
public void method2(int a, int b)
{
tryAndTryAgain(() -> {
// logic 2
System.out.println(a + " " + b);
throw new RuntimeException();
});
}
public static void tryAndTryAgain(Runnable tryThis)
{
try
{
tryThis.run();
}
catch (Exception e)
{
new Timer().schedule(new TimerTask()
{
#Override
public void run()
{
tryAndTryAgain(tryThis);
}
}, 1000);
// existing exception handling logic
}
}
}
The exact structure depends on your specfic implementation, but it should give you an idea how to structure it. The benefit is that all those methods can concentrate on the business logic, and the retry logic and exception handling are done in a util method. And that util method doesn't even need to know anything about parameters, methods, or anything, because all the business logic is contained in the Runnable.

Java SE 7: alternative to try-catch for testing

I have a bunch of similar methods called from #Before beforeTest() in a test class:
//...
private void addClientDetails() {
try {
clientDetailsService.addClientDetails(testClient);
} catch (Exception e) {
}
}
private void addUserRoles() {
try {
adminController.addUserRoles(addedRoles);
} catch (Exception e) {
}
}
private void deleteAddedRoles() {
for (String role : addedRoles) {
try {
adminController.deleteUserRole(role);
} catch (Exception e) {
}
}
}
private void deleteClients() {
try {
clientsController.deleteClient(testClient.getClientId());
} catch (Exception e) {
}
}
//...
It is really unnecessary to catch possible exceptions and inconvenient to add some ifs here. These are the auxiliary methods to prepare tests or clean up after tests.
How to get rid of those ridiculous try {...} catch (...) {} constructs?
The idea was to create a new method with Runnable argument but this leads to even more cumbersome syntax:
private void deleteClients() {
trySilently(new Runnable() {
#Override
public void run() {
}
});
}
private void trySilently(Runnable task) {
try {
task.run();
} catch (Exception e) {
//do nothing
}
}
In JDK 1.8 method reference can help. But is there any beautiful solution in terms of JDK 1.7?
It is understood ignoring exceptions is a bad practice. Nevertheless the question is exactly how to do it in a graceful way.
You can declare that those methods throw exceptions, e.g.:
private void addClientDetails() throws Exception {
clientDetailsService.addClientDetails(testClient);
}
...then use reflection to call them:
String[] methods = {"addClientDetails", "addUserDetails" /*, ...*/};
for (String method : methods) {
try {
TestClass.class.getMethod(method).invoke(testObject);
}
catch (Exception e) {
// STRONGLY RECOMMEND DOING SOMETHING HERE SO YOU'RE NOT SILENTLY
// IGNORING EXCEPTIONS
}
}
(You'll need to keep the handler in deleteAddedRoles, though, since it loops, if you really want to ignore exceptions from adminController.deleteUserRole.)
Note: It seems very strange to be completely ignoring those exceptions. It's hard to imagine how you can trust your test results if you silently ignore exceptions from the test code. But I'm assuming you know what you're doing... :-)
In TestNG there is no problem for method annotated with #BeforeClass/#BeforeMethod to throw exception.
Why wouldn't you just
#BeforeClass
private void addClientDetails() throws Exception{
clientDetailsService.addClientDetails(testClient);
}
This also works for #Test methods.
Silenty catching exception is very bad idea. How could you trust your tests then? are you sure that exceptions tha occured is no problem indeed? If yes, then exception should not be thrown in first place.
Also, you could redesing your API to use unchecked exceptions. Just wrap any checked exceptions in RuntimeException, and throw RuntimeException.

Testing Constructor with JUnit

I need to test a constructor which throws an exception using JUnit.
Below is the constructor:
public EISThirdPartyClient(ClientConfiguration _config, String _serviceURL)
throws EISClientException {
super(_config, _serviceURL);
try {
ObjectMapperHolder.initialize(_config);
} catch (Exception e) {
throw new EISClientException(e);
}
}
Below is the test case:
#Test
public void testEISThirdPartyClientConctructor() throws EISClientException {
#SuppressWarnings("unused")
EISThirdPartyClient client = new EISThirdPartyClient(new ClientConfiguration(), "url");
boolean caughtException = false;
try {
ObjectMapperHolder.initialize(null);
} catch (Exception ex) {
if (ex instanceof EISClientException) {
caughtException = true;
assertTrue(ex.getCause() instanceof EISClientException);
} else {
ex.printStackTrace();
fail("Uncaught exception");
}
}
assertTrue(caughtException);
}
I am getting java.lang.AssertionError, which isn't what I'm expecting. Can someone tell me what I am doing wrong?
You're testing the wrong thing - you want to ensure that the construction of your object fails, not that it bails out when ObjectMapperHolder bails out.
You can also greatly simplify the test - you can expect that EISClientException is thrown without needing to do any further validation of the exception.
The main point is to get the test to fail with the minimum required amount of work. It seems that passing null as your configuration might do it, so here's an example with that:
#Test(expected = EISClientException.class)
public void testEISThirdPartyClientConctructor() throws EISClientException {
new EISThirdPartyClient(null, "url");
}
If this doesn't quite suit your needs, you may want to look into a mocking framework like Mockito to provide behavior when you are in the critical section of your code.

Access Try-Catch block's code in another class

May be it could be silly,but I want to clear my the technical understanding of this code:
import netscape.*;//ldap jar
public class A {
public void method() {
...
try {
//code is written here.
LDAPSearchResults lsr = ldi.search(LDAPConnectionInfo.MY_SEARCHBASE,LDAPConnectionInfo.MY_SCOPE,LDAPConnectionInfo.MY_FILTER,null,false);
while(lsr.hasMoreElements()){
LDAPEntry findEntry = (LDAPEntry)lsr.nextElement();
} catch(...) {
}
}
}
Now I call another class
public class B {
A a = new A();
//here I want to use attributeName
}
How could I access A class's member(in try block) in B class.
Any way to handle try block code for reuse in another class.
How could I handle all those exception in another class.
Any modification should I need...
Calling method of Object type.
public class C{
private String attributeName;
public String getAttributeName() {
return attributeName;
}
public Object method(){
attributeName=lAttribute.getName();
}
}
How could print this Object type method into String(in a jsp page)... any inputs
You'll need a member in class A and a getter:
public class A {
private String attributeName;
public String getAttributeName() {
return attributeName;
}
public void method(){
...
try {
//code is written here.
attributeName = lAttribute.getName();
}
catch() {
}
}
}
Then:
public class B {
A a = new A();
// somewhere
String str = a.getAttributeName();
}
There's no way to access a method's private variables like you did in the original example, as they only exist on the stack during the method call.
Edit: I noticed another question:
How could I handle all those exception in another class.
I assume you want to call your method somewhere else and catch the exceptions there. In that case you can use the throws keyword to communicate that your method will pass exceptions to the caller:
public class A {
public void method() throws IOException {
//code is written here.
String attributeName = lAttribute.getName();
}
public void anotherMethod() {
try {
method();
} catch(IOException ex) {
...
}
}
}
then if some other piece of code calls method it will be forced to either handle or further propagate the exception.
How could I handle all those exception in another class.
In your calling class you can catch Throwable (which will catch all exceptions and errors)
try {
....
}
catch (Throwable t) {
//do something with the throwable.
}
if you do not want to catch Errors (Ive only done this when messing around with ImageIO and had memory problems) in Java then catch Exception instead
Any way to handle try block code for reuse in another class
here you could create a method in another class and then call it within your try /catch block
public class XYX {
public void methodForTry() throws Exception {
//do something
}
}
try {
new XYZ().methodForTry();
}
catch (Exception e){
}
You may or may not want to create new XYZ here. It depends what state this object may or may not hold.
As to the last questions I think Tudor's answer covers this
Your question may be about extracting the code template
try { ... do stuff ... }
catch (MyFirstException e) { ...handle ... }
catch (MySecondException e) { ...handle ... }
... more catch ...
Where you only want to change the ... do stuff ... part. In that case you'd need closures, which are coming with Java 8, and today you'd need something quite cumbersome, of this sort:
public static void tryCatch(RunnableExc r) {
try { r.run(); }
catch (MyFirstException e) { ...handle ... }
catch (MySecondException e) { ...handle ... }
... more catch ...
}
where RunnableExc would be an
interface RunnableExc { void run() throws Exception; }
and you'd use it this way:
tryCatch(new RunnableExc() { public void run() throws Exception {
... do stuff ...
}});
why not return it?
public String method() {
String attributeName
try {
//code is written here.
attributeName = lAttribute.getName();
} catch(...) {
}
return attributeName;
}
public class B {
A a = new A();
String attributeName = a.method();
}

In Java how can I validate a thrown exception with JUnit?

When writing unit tests for a Java API there may be circumstances where you want to perform more detailed validation of an exception. I.e. more than is offered by the #test annotation offered by JUnit.
For example, consider an class that should catch an exception from some other Interface, wrap that exception and throw the wrapped exception. You may want to verify:
The exact method call that throws the wrapped exception.
That the wrapper exception has the original exception as its cause.
The message of the wrapper exception.
The main point here is that you want to be perf additional validation of an exception in a unit test (not a debate about whether you should verify things like the exception message).
What's a good approach for this?
In JUnit 4 it can be easily done using ExpectedException rule.
Here is example from javadocs:
// These tests all pass.
public static class HasExpectedException {
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void throwsNothing() {
// no exception expected, none thrown: passes.
}
#Test
public void throwsNullPointerException() {
thrown.expect(NullPointerException.class);
throw new NullPointerException();
}
#Test
public void throwsNullPointerExceptionWithMessage() {
thrown.expect(NullPointerException.class);
thrown.expectMessage("happened?");
thrown.expectMessage(startsWith("What"));
throw new NullPointerException("What happened?");
}
}
As provided in your answer, it's a good approach. In addition to this:
You could wrap the function expectException into a new Annotation, called ExpectedException.
An annotated method would look like this:
#Test
#ExpectedException(class=WrapperException.class, message="Exception Message", causeException)
public void testAnExceptionWrappingFunction() {
//whatever you test
}
This way would be more readable, but it's exactly the same approach.
Another reason is: I like Annotations :)
Looking at the proposed answers, you can really feel the pain of not having closures in Java. IMHO, the most readable solution is ye good old try catch.
#Test
public void test() {
...
...
try {
...
fail("No exception caught :(");
}
catch (RuntimeException ex) {
assertEquals(Whatever.class, ex.getCause().getClass());
assertEquals("Message", ex.getMessage());
}
}
For JUNIT 3.x
public void test(){
boolean thrown = false;
try{
mightThrowEx();
} catch ( Surprise expected ){
thrown = true;
assertEquals( "message", expected.getMessage());
}
assertTrue(thrown );
}
Until this post I've done my exception validation by doing this:
try {
myObject.doThings();
fail("Should've thrown SomeException!");
} catch (SomeException e) {
assertEquals("something", e.getSomething());
}
I spent a few moments thinking about the issue though and came up with the following (Java5, JUnit 3.x):
// Functor interface for exception assertion.
public interface AssertionContainer<T extends Throwable> {
void invoke() throws T;
void validate(T throwable);
Class<T> getType();
}
// Actual assertion method.
public <T extends Throwable> void assertThrowsException(AssertionContainer<T> functor) {
try {
functor.invoke();
fail("Should've thrown "+functor.getType()+"!");
} catch (Throwable exc) {
assertSame("Thrown exception was of the wrong type! Expected "+functor.getClass()+", actual "+exc.getType(),
exc.getClass(), functor.getType());
functor.validate((T) exc);
}
}
// Example implementation for servlet I used to actually test this. It was an inner class, actually.
AssertionContainer<ServletException> functor = new AssertionContainer<ServletException>() {
public void invoke() throws ServletException {
servlet.getRequiredParameter(request, "some_param");
}
public void validate(ServletException e) {
assertEquals("Parameter \"some_param\" wasn't found!", e.getMessage());
}
public Class<ServletException> getType() {
return ServletException.class;
}
}
// And this is how it's used.
assertThrowsException(functor);
Looking at these two I can't decide which one I like more. I guess this is one of those issues where achieving a goal (in my case, the assertion method with functor parameter) isn't worth it in the long run since it's just a lot easier to do those 6+ of code to assert the try..catch block.
Then again, maybe my 10 minute result of problem solving at friday evening just isn't the most intelligent way to do this.
#akuhn:
Even without closures we can get a more readable solution (using catch-exception):
import static com.googlecode.catchexception.CatchException.*;
public void test() {
...
...
catchException(nastyBoy).doNastyStuff();
assertTrue(caughtException() instanceof WhateverException);
assertEquals("Message", caughtException().getMessage());
}
The following helper method (adapted from this blog post) does the trick:
/**
* Run a test body expecting an exception of the
* given class and with the given message.
*
* #param test To be executed and is expected to throw the exception.
* #param expectedException The type of the expected exception.
* #param expectedMessage If not null, should be the message of the expected exception.
* #param expectedCause If not null, should be the same as the cause of the received exception.
*/
public static void expectException(
Runnable test,
Class<? extends Throwable> expectedException,
String expectedMessage,
Throwable expectedCause) {
try {
test.run();
}
catch (Exception ex) {
assertSame(expectedException, ex.getClass());
if (expectedMessage != null) {
assertEquals(expectedMessage, ex.getMessage());
}
if (expectedCause != null) {
assertSame(expectedCause, ex.getCause());
}
return;
}
fail("Didn't find expected exception of type " + expectedException.getName());
}
The test code can then invoke this as follows:
TestHelper.expectException(
new Runnable() {
public void run() {
classInstanceBeingTested.methodThatThrows();
}
},
WrapperException.class,
"Exception Message",
causeException
);
i did something very simple
testBla(){
try {
someFailingMethod()
fail(); //method provided by junit
} catch(Exception e) {
//do nothing
}
}
For JUnit 5 it is much easier:
#Test
void testAppleIsSweetAndRed() throws Exception {
IllegalArgumentException ex = assertThrows(
IllegalArgumentException.class,
() -> testClass.appleIsSweetAndRed("orange", "red", "sweet"));
assertEquals("this is the exception message", ex.getMessage());
assertEquals(NullPointerException.class, ex.getCause().getClass());
}
By returning the exception object itself, assertThrows() allows you to test every aspect regarding your thrown exceptions.
I made a helper similar to the other posted ones:
public class ExpectExceptionsExecutor {
private ExpectExceptionsExecutor() {
}
public static void execute(ExpectExceptionsTemplate e) {
Class<? extends Throwable> aClass = e.getExpectedException();
try {
Method method = ExpectExceptionsTemplate.class.getMethod("doInttemplate");
method.invoke(e);
} catch (NoSuchMethodException e1) {
throw new RuntimeException();
} catch (InvocationTargetException e1) {
Throwable throwable = e1.getTargetException();
if (!aClass.isAssignableFrom(throwable.getClass())) {
// assert false
fail("Exception isn't the one expected");
} else {
assertTrue("Exception captured ", true);
return;
}
;
} catch (IllegalAccessException e1) {
throw new RuntimeException();
}
fail("No exception has been thrown");
}
}
And the template the client should implement
public interface ExpectExceptionsTemplate<T extends Throwable> {
/**
* Specify the type of exception that doInttemplate is expected to throw
* #return
*/
Class<T> getExpectedException();
/**
* Execute risky code inside this method
* TODO specify expected exception using an annotation
*/
public void doInttemplate();
}
And the client code would be something like this:
#Test
public void myTest() throws Exception {
ExpectExceptionsExecutor.execute(new ExpectExceptionsTemplate() {
#Override
public Class getExpectedException() {
return IllegalArgumentException.class;
}
#Override
public void doInttemplate() {
riskyMethod.doSomething(null);
}
});
}
It looks really verbose but if you use an IDE with good autocompletion you will only need to write the type of exception and the actual code under test. (the rest will be done by the IDE :D)

Categories