#Transactional not working when i throw exception on next line - java

I don't understand the below behavior:
I have a method:
#Transactional
public void processRejection(final Path path) {
try {
//some code here
} catch (final Exception e) {
this.handleException(e));
}
}
which calls the below which does a saves an entity which doesn't yet exists in the database:
void handleException(final Throwable e) {
this.filesMonitoringJpaManager.save(someEntityHere);
throw new Exception(...)
}
Now the strange is when I comment the throw new Exception(...) the save works, but when I uncomment throw new Exception(...) then the save doesn't work and I have no clue why?
What strange behavior is that from JPA or Hibernate? Is it something about Java Exception mechanism which I don't understand?

#Transactional is meant to roll back when something goes wrong (an exception is thrown). You're saving an entity in the catch block, but you're rethrowing an exception causing the transactional method to roll back.
But you can specify an exception, that will not cause rollback:
#Transactional(noRollbackFor = {MyException.class})
public void processRejection(final Path path) {
try {
//somecode here whatever
} catch (final Exception e) {
this.handleException(e));
}
}
void handleException(final Throwable e) {
this.filesMonitoringJpaManager.save(someEntityHere);
throw new MyException(...)
}
This works for org.springframework.transaction.annotation.Transactional. If you're using javax.transaction.Transactional, then you can achieve it by using dontRollbackOn property.

Related

Hibernate : throw exception in #PostUpdate

I have this code on an Spring/Hibernate webapp :
Entity :
#Entity
#Table(name = "ARTICLE")
#EntityListeners(ArticleEntityListener.class)
public class ArticleLocaliseBean extends EntiteTracee {
...
Listenner :
public class ArticleLocaliseEntityListener {
#PostUpdate
#PostPersist
private void checkQuantite(ArticleBean article) throws BusinessException {
if (article.getQuantiteStock() < 0) {
throw new BusinessException(exceptionMsg);
}
}
This code called after each update or persist on Article entity.
The problem is when an exception is thrown for negative quantity, hibernate convert the BusinessException on a RuntimeException and perform a rollback of the transaction.
java.lang.RuntimeException: xxx.exceptions.BusinessException: exceptionMsg.
at org.hibernate.ejb.event.ListenerCallback.invoke(ListenerCallback.java:53)
at org.hibernate.ejb.event.EntityCallbackHandler.callback(EntityCallbackHandler.java:94)
at org.hibernate.ejb.event.EntityCallbackHandler.postUpdate(EntityCallbackHandler.java:83)
at org.hibernate.ejb.event.EJB3PostUpdateEventListener.handlePostUpdate(EJB3PostUpdateEventListener.java:70)
at org.hibernate.ejb.event.EJB3PostUpdateEventListener.onPostUpdate(EJB3PostUpdateEventListener.java:62)
at org.hibernate.action.EntityUpdateAction.postUpdate(EntityUpdateAction.java:199)
How can I makes Hibernate throw a checked exception an not a Runtime ? I don't want a rollback of the transaction when an exception is thrown.
Thanks.
The exception is thrown upon call on an API method, such as persist(). These methods however are not declared to throw exceptions (there is no throws clause in their signature). Hibernate has to wrap any checked exception in a runtime exception to respect method's signature.
To avoid rolling back, you can catch the runtime exception and check for its cause.
try {
em.persist(entity);
} catch (RuntimeException e) {
if (e.getCause() instanceof BusinessException) {
// Fix the problem the way you want
} else {
throw e;
}
}

Java with Groovy handling of closures throwing Exceptions

We have a system that is possible to customise using groovy scripts and I've spotted a very strange effect on the type of exceptions throw from these scripts.
We have a groovy script with the following:
process {
throw new Exception("weeee")
}
Process is defined as a Closure in the base class of the script:
public abstract class ScriptBaseClass extends Script {
Closure process;
public void process( Closure code ) {
process = (Closure) code.clone();
}
}
In the Java class that actually runs the scripts we have the following method (omitted all the set up code as it doesn't seem relevant):
public void process() {
try {
script.process.call();
} catch (Exception e) {
logger.debug("exception thrown from groovy script", e);
throw e;
}
}
Note the process method here doesn't declare it throws any exceptions. However it quite clearly re-throws the Exception e that it caught. This code is valid, it compiles and runs quite happily. It throws the Exception as I wanted.
Does any one know how this is legal code? In theory I shouldn't be able to throw a checked exception out of a method that doesn't declare that it throws it.
It works because Java compiler (starting since Java 7) can determine re-thrown exception. For catch (Exception e) it thinks it's RuntimeException because there were no other (checked) exception declared in call().
You can read about it there, for example: https://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html
So this code compiles perfectly:
public void xxxxx() {
try {
System.out.println('Hi!'); //or anything else w/o declared exceptions
} catch (Exception e) {
throw e;
}
}
Java compiled sees that only RuntimeException could be caught here, so it doesn't ask you do declare anything.
But for this:
public void xxxxx() {
try {
throw new IOException(); //or anything that have declared checked exception
} catch (Exception e) {
throw e;
}
}
it will fail to compile, because IOException could be caught and re-thrown
Introducing closures or anything Groovy related is unnecessary complexity. The following is valid Java code:
public class Demo {
public void someMethod() {
try {
System.out.println("Hello");
} catch (Exception e) {
throw e;
}
}
}
Note that the following is not valid and will not compile:
import java.sql.*;
public class Demo {
public void someMethod() {
try {
Connection c = DriverManager.getConnection("", "", "");
} catch (SQLException e) {
throw e;
}
}
}
Groovy and the JVM don't really care about an exception being a checked one or not. Only the Java compiler cares about this here. In fact you can use the catch on any RuntimeException or its parent classes (of which Exception is one) without requiring it being declared as thrown from something called in the try-block. So it is fine by the compiler to catch Exception or Throwable even. Of course, from a program logic view it is an entirely different matter.

Java 8: How do I work with exception throwing methods in streams?

Suppose I have a class and a method
class A {
void foo() throws Exception() {
...
}
}
Now I would like to call foo for each instance of A delivered by a stream like:
void bar() throws Exception {
Stream<A> as = ...
as.forEach(a -> a.foo());
}
Question: How do I properly handle the exception? The code does not compile on my machine because I do not handle the possible exceptions that can be thrown by foo(). The throws Exception of bar seems to be useless here. Why is that?
You need to wrap your method call into another one, where you do not throw checked exceptions. You can still throw anything that is a subclass of RuntimeException.
A normal wrapping idiom is something like:
private void safeFoo(final A a) {
try {
a.foo();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
(Supertype exception Exception is only used as example, never try to catch it yourself)
Then you can call it with: as.forEach(this::safeFoo).
If all you want is to invoke foo, and you prefer to propagate the exception as is (without wrapping), you can also just use Java's for loop instead (after turning the Stream into an Iterable with some trickery):
for (A a : (Iterable<A>) as::iterator) {
a.foo();
}
This is, at least, what I do in my JUnit tests, where I don't want to go through the trouble of wrapping my checked exceptions (and in fact prefer my tests to throw the unwrapped original ones)
This question may be a little old, but because I think the "right" answer here is only one way which can lead to some issues hidden Issues later in your code. Even if there is a little Controversy, Checked Exceptions exist for a reason.
The most elegant way in my opinion can you find was given by Misha here Aggregate runtime exceptions in Java 8 streams
by just performing the actions in "futures". So you can run all the working parts and collect not working Exceptions as a single one. Otherwise you could collect them all in a List and process them later.
A similar approach comes from Benji Weber. He suggests to create an own type to collect working and not working parts.
Depending on what you really want to achieve a simple mapping between the input values and Output Values occurred Exceptions may also work for you.
If you don't like any of these ways consider using (depending on the Original Exception) at least an own exception.
You might want to do one of the following:
propagate checked exception,
wrap it and propagate unchecked exception, or
catch the exception and stop propagation.
Several libraries let you do that easily. Example below is written using my NoException library.
// Propagate checked exception
as.forEach(Exceptions.sneak().consumer(A::foo));
// Wrap and propagate unchecked exception
as.forEach(Exceptions.wrap().consumer(A::foo));
as.forEach(Exceptions.wrap(MyUncheckedException::new).consumer(A::foo));
// Catch the exception and stop propagation (using logging handler for example)
as.forEach(Exceptions.log().consumer(Exceptions.sneak().consumer(A::foo)));
I suggest to use Google Guava Throwables class
propagate(Throwable throwable)
Propagates throwable as-is if it is an
instance of RuntimeException or Error, or else as a last resort, wraps
it in a RuntimeException and then propagates.**
void bar() {
Stream<A> as = ...
as.forEach(a -> {
try {
a.foo()
} catch(Exception e) {
throw Throwables.propagate(e);
}
});
}
UPDATE:
Now that it is deprecated use:
void bar() {
Stream<A> as = ...
as.forEach(a -> {
try {
a.foo()
} catch(Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
});
}
You can wrap and unwrap exceptions this way.
class A {
void foo() throws Exception {
throw new Exception();
}
};
interface Task {
void run() throws Exception;
}
static class TaskException extends RuntimeException {
private static final long serialVersionUID = 1L;
public TaskException(Exception e) {
super(e);
}
}
void bar() throws Exception {
Stream<A> as = Stream.generate(()->new A());
try {
as.forEach(a -> wrapException(() -> a.foo())); // or a::foo instead of () -> a.foo()
} catch (TaskException e) {
throw (Exception)e.getCause();
}
}
static void wrapException(Task task) {
try {
task.run();
} catch (Exception e) {
throw new TaskException(e);
}
}
More readable way:
class A {
void foo() throws MyException() {
...
}
}
Just hide it in a RuntimeException to get it past forEach()
void bar() throws MyException {
Stream<A> as = ...
try {
as.forEach(a -> {
try {
a.foo();
} catch(MyException e) {
throw new RuntimeException(e);
}
});
} catch(RuntimeException e) {
throw (MyException) e.getCause();
}
}
Although at this point I won't hold against someone if they say skip the streams and go with a for loop, unless:
you're not creating your stream using Collection.stream(), i.e. not straight forward translation to a for loop.
you're trying to use parallelstream()

Is there an easier way to combine #Transactional with logging?

I'm trying out Spring for the first time but am having a problem with #Transactional. There are certain parts of my app that I need to log exceptions in the method instead of bubbling them up to, say, main(). The issue though is that those methods which are labeled with #Transactional won't be rolled back if an exception occurs.
In short, this wont' work
#Transactional
public void doStuff() {
try {
//Do something that might cause an Exception
} catch (Exception e) {
log.error("Exception when trying to do stuff", e);
}
}
Because from my understanding the transaction will never be rolled back if an exception occurs.
The only solution I could come up with:
public void doStuff() {
try {
doStuff0();
} catch (Exception e) {
log.error("Error encountered while attempting to join servers", e);
}
}
#Transactional
protected void doStuff0() {
//Do something that might cause an Exception
}
That's ugly though, uses a pattern I don't like, and is in this example almost twice as much code.
Is there another alternative to log the exception AND rollback the transaction?
There is in fact a simple way to do what you want. Architectural Astronaut discussions about if it's a good idea or when it' appropriate aside, sometimes you just need it to work :) :
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
Easy as that.
Just rethrow the exception:
#Transactional
public void doStuff() {
try {
//Do something that might cause an Exception
} catch (Exception e) {
log.error("Exception when trying to do stuff", e);
throw e;
}
}

performing clean up and passing the exception to the caller

I need to do some initialization and clean it up in case of any exception. I'd still like the exception to be passed to the caller. The problem is I now have to declare this method as throws Throwable and then I have to explicitly handle this throwable in the caller, just as if all procedures don't throw Throwables implicitly already. Stupid isn't it?
try {
init_step1();
init_step2();
}
catch (Throwable th) {
clean();
throw th;
}
One way of doing this is to perform the cleanup in a finally block instead, noticing whether there's been an exception by whether you actually got to the end of the try block or not:
boolean success = false;
try {
// Stuff here
success = true;
} finally {
if (!success) {
clean();
}
}
Stupid is fighting against checked exceptions. You have to throw something different if you don't want to require every caller to handle it. just throw a RuntimeException
public void myMethod() throws RuntimeException {
try {
init_step1();
init_step2();
}
catch (Throwable th) {
clean();
throw new RuntimeException(th);
}
}
why do you catch Throwable in first place anyway? init_step1() and init_step2() doesn't throw an exception?
#Jon Skeet's solution is the cleanest. Another solution which may interest you.
try {
// Stuff here
} catch(Throwable t) {
clean(t);
// bypasses the compiler check
Thread.currentThread().stop(t);
}
I would only suggest using this approach if you needed to know the exception thrown. e.g. For resources I have which are closable, I record the exception which triggered their close. This way if I try to use the resource and it is closed I can see why it is closed.
private void checkClosed() {
if (closed)
throw new IllegalStateException("Closed", reasonClosed);
}

Categories