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;
}
}
Related
We all write from time to time code like this:
try {
// ... some code.
} catch (SomeException e) {
// ... No action is required, just ignore.
}
Is there any standard code fragment like annotation to show we really intend to ignore exception? Something that shows to other team members and static analyzers we really need to skip this situation like InterruptedException after Thread.sleep()? Something like:
Exception.ignore(e);
Googled around but have not found something standard for such case.
This is especially relevant to tests that assure exceptions:
try {
action();
fail("We expected this to fail.");
} catch (ExpectedException e) {
ignore(e, "OK, so far so good.");
}
The only way to ignore an exception is to catch & swallow it, being very specific on the exception of course, you wouldn't want to catch Exception e, that would be a very bad idea.
try{
... //code
}
catch( VerySpecificException ignore){
Log(ignore);
}
Logging is obviously optional but a good practice.
in order to keep the code up with your exception handling or ignoring, it's nice to name the exception var as ignored:
try {
action();
} catch (ExpectedException ignored ) {}
Concerning your update referring to testing, if you use a testing framework, you can annotate the test in such a way that an exception is expected, e.g. using TestNG
#Test(expectedExceptions = ClassNotFoundException.class)
public void testSomething() {
// will succeed if a ClassNotFoundException is thrown
}
We need to have two functions. They do the same thing but one handles the exceptions and one throws the exception. Note: If to handle exception, the exception has to be handled in the commonFunc() below. It would not work to handle the exception in functionHandlesEx() because to handle the function it needs the variable only available in commonFunc(). In order to re-use code, we got the following. Do you see any problem with it (I can see one problem is: the function throws exception but actually no exception is thrown when isExceptionHandled is true----but Java allows this)? Any better way to do this? We are in Java 6. Thanks.
public void functionThrowsEx() throws Exception e
{
commonFunc(false); //false means does not handle exception
}
public void functionHandlesEx()
{
try
{
commonFunc(true); //true means handle exception
}
catch (Exception e)
{
// do nothing as exception handled
}
}
private void commonFunc(final boolean isExceptionHandled) throws Exception
{
try
{
....
}
catch (Exception e)
{
if (isExceptionHandled)
{
//handle the exception
}
else
{
throw e;
}
}
}
This seems like an overly complicated approach to handling the exception. I understand its toy code to show what you are doing, but I haven't encountered many reasons to create nested calls in order to handle exceptions.
Ideally, the code that can cause the exception should have the means to handle the exception in it, using try...catch, and maybe finally. This logical flow looks like it would be pretty complex in a non-trivial application, and would lead to increased complexity and difficulty in debugging.
You should get rid of the two functions, and avoid nesting try/catch blocks. If you must nest them, make it has straigtfoward as possible by keeping the logic in the same method.
From the code, I'm guessing you want to handle the exception differently based on the state of the program. This code is too complex, and will be difficult to understand for a non trivial app. A better way would be to keep functionHandlesEx and put the exception recovery logic in the handler function.
public void functionHandlesEx() {
try {
//logic here;
}
}
catch (Exception e) {
if(iWantToHandleException) {
//handle exception
}
//do nothing otherwise. Use the finally block for anything else they have in common.
}
}
This is much simpler to understand, and it shouldn't be too hard to refactor it into this form.
This is what I have:
#Test
public testSendMessageToStub() {
// under the hood sends message
// if exception occurrs
// it will be catched and message will be put on retry
object.sendMessage();
}
Is there any way to mark test as failed if exception has occurred but was handled in catch block in the sendMessage() method?
Thanks
EDIT: It seems like I was too fixated on these legacy tests and how they were used, that totally missed the fact of sendMessage returning a response with a status code (!!!). So now I just assert status codes, can expand these tests into more detailed scenarios and spin them on jenkins. I would like to avoid to answer how these tests were checked previously. The thought to check for status codes came to me after reading Plux's answer. Thanks!
Exactly what you are looking for is not possible with JUnit as far as I know.
If you really would want to test this, you could store some information about the exception in the catch-block where it is handled in the sendMessage() method.
A better option, in my opinion, could be to test the output or state of the object. If the state/output is exactly the same as when an exception doesn't occur, then whats the point of testing it? Do you have an overly broad catch-block?
EDIT: To AdityaTS, I dont have enough reputation to comment on a post, but my comment: you have not supplied all the code, so I can not say for sure, but my guess is that its the Logger.getLogger IN the catch-block that casts the ClassNotFoundException. (Either that or loadConnectionInfo()) see http://docs.oracle.com/javase/7/docs/api/java/lang/ClassNotFoundException.html
You cannot do this without modifying sendMessage method. If for example you catch the exception there but choose to ignore it and just return some value, code outside of the method doesn't know it. You can get around this by refactoring the code of object: move the code that handles the exception to a separate method, called e.g. handleException. Then, in your test you can create a subclass where handleException will execute the original handleException from superclass, but additionally set some flag which you will be able to read in your test and in this way tell that the exception was thrown. However, if you cannot modify the code for object's class, I'm afraid you're out of luck.
So you expect the exception to propagate out of the sendMessage() method, right?
This is another way to write a test that verifies an exception you expect will be thrown.
#Test (expected = MyExpectedException.class)
public testSendMessageToStub() {
// under the hood sends message
// if exception occurrs
// it will be catched and message will be put on retry
object.sendMessage();
}
And it's usually best to be as specific as possible (e.g. MyExpectedException.class over Exception.class)
The exception generated in the sendMessage() class will be available in the test method. Add a try catch block around the sendMessage() method like this
#Test
public testSendMessageToStub() {
try
{
object.sendMehssage();
}
catch(Excpetion e) //Use more specific exception type if you know
{
fail(e.getMessage());
}
}
I have tried this in my code. It worked for me. Let me know.
public DBConnectionInfo connectionInit()
{
loadConnectionInfo();
try
{
Class.forName(dbObject.getDriver());
} catch (Exception e)
{
Logger lgr = Logger.getLogger(PostgreLocationManager.class.getName());
lgr.log(Level.SEVERE, e.getMessage(), e);
}
try
{
dbObject.setConnection(DriverManager.getConnection(dbObject.getDatabaseURL(), dbObject.getUserName(),
dbObject.getPassword()));
} catch (Exception e)
{
Logger lgr = Logger.getLogger(PostgreLocationManager.class.getName());
lgr.log(Level.SEVERE, e.getMessage(), e);
}
return dbObject;
}
The test case for the above class.
#Test
public void testDriverFailure()
{
when(dbModelObject.getDriver()).thenReturn("driver");
when(dbModelObject.getDatabaseURL()).thenReturn("jdbc:postgresql://127.0.0.1:5432/testdb");
when(dbModelObject.getUserName()).thenReturn("postgres");
when(dbModelObject.getPassword()).thenReturn("postgres");
try
{
dbConnector.connectionInit();
} catch (Exception e)
{
assertTrue(e instanceof ClassNotFoundException);
}
verify(dbModelObject).getDriver();
}
This is very odd to me. RuntimeException inherits from Exception, which inherits from Throwable.
catch(Exception exc) { /* won't catch RuntimeException */
but
catch(Throwable exc) { /* will catch RuntimeException */
I know RuntimeException is special in that it's unchecked. But to my understanding that applies just to whether exceptions have to be declared, not whether they are caught. And even then, I don't know why this logic would break on catching Throwable.
This is pretty relevant to me since I have a situation where RuntimeException can be thrown in a terminal operation. I'm not sure the name for this pattern, but something like, my class EmailRoller takes an array of Callbacks. The code looks like this:
for(Callback cb : callbacks) {
try {
cb.call(item);
}
catch(Exception exc) {
logger.error("Error in callback: ", exc);
}
}
So this is a case where something like an OOME needs to fly through, because if one of these callbacks consumes all machine memory, that sure as heck is going to affect the running of the other ones. But a NullPointerException? Or an IndexOutOfBoundsException? Those will affect the callback but won't prevent the others from running.
Also, this is a bit of an enterprise design. Different programmers or teams can add callbacks to process the item, but they should be isolated from each other. This means, as the programmer responsible for insulating these callbacks from each other, I shouldn't rely on them to make sure errors don't slip through. Catching Exception should be about the right line, but it isn't because RuntimeException slips through. So my more general question is: what's a good pattern here? Just catch(Exception | RuntimeException exc), which I believe is a syntax error because of the inheritance?
The premise of the question is flawed, because catching Exception does catch RuntimeException. Demo code:
public class Test {
public static void main(String[] args) {
try {
throw new RuntimeException("Bang");
} catch (Exception e) {
System.out.println("I caught: " + e);
}
}
}
Output:
I caught: java.lang.RuntimeException: Bang
Your loop will have problems if:
callbacks is null
anything modifies callbacks while the loop is executing (if it were a collection rather than an array)
Perhaps that's what you're seeing?
catch (Exception ex) { ... }
WILL catch RuntimeException.
Whatever you put in catch block will be caught as well as the subclasses of it.
Catching Exception will catch a RuntimeException
I faced similar scenario. It was happening because classA's initilization was dependent on classB's initialization. When classB's static block faced runtime exception, classB was not initialized. Because of this, classB did not throw any exception and classA's initialization failed too.
class A{//this class will never be initialized because class B won't intialize
static{
try{
classB.someStaticMethod();
}catch(Exception e){
sysout("This comment will never be printed");
}
}
}
class B{//this class will never be initialized
static{
int i = 1/0;//throw run time exception
}
public static void someStaticMethod(){}
}
And yes...catching Exception will catch run time exceptions as well.
class Test extends Thread
{
public void run(){
try{
Thread.sleep(10000);
}catch(InterruptedException e){
System.out.println("test1");
throw new RuntimeException("Thread interrupted..."+e);
}
}
public static void main(String args[]){
Test t1=new Test1();
t1.start();
try{
t1.interrupt();
}catch(Exception e){
System.out.println("test2");
System.out.println("Exception handled "+e);
}
}
}
Its output doesn't contain test2 , so its not handling runtime exception.
#jon skeet, #Jan Zyka
I have a very basic question about best practice of using try/catch.
I have a simple function (DAO) like this:
public void addVehicle(Vehicle vehicle) {
em.getTransaction().begin();
em.persist(vehicle);
em.getTransaction().commit();
}
and using DAO function inside web service:
#WebMethod(operationName = "addVehicle")
public void addVehicle(Vehicle vehicle) {
try {
vehicleDAO.addVehicle(vehicle);
System.out.print("Vehicle added");
} catch (Exception e) {
e.printStackTrace();
}
}
OR is better using try/catch inside DAO function like this:
public void addVehicle(Vehicle vehicle) {
try {
em.getTransaction().begin();
em.persist(vehicle);
em.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
}
}
There is no perfect rule for that.
Often code is clearer and less complex if exceptions are catched as early as needed, but as late as possible.
You should think who has to take an action when that Exception happens, this decides if you catch it inside the method (addVehicle) or if you throw it such that the caller has to catch it.
E.g:
public void addVehicle(Vehicle vehicle) throws SQLException{
em.getTransaction().begin();
em.persist(vehicle);
em.getTransaction().commit();
}
In this example the caller has to catch.
Further only in few situations you should catch Exception or RunTimeException, better
catch that specific Exception, like IOException instead of Exception.
Somewhere in your code you will need a "last line of defense" where it make sense to catch (Exception ex). This is needed to handle errors that should not happen.
When deciding where to handle a specific kind of exception, the best rule of thumb is to stop looking at the micro details of your code, take a step back to reason about your program's logic and consider these things:
Is the exception something that your program's current operation cannot recover from? If yes, it only makes sense to put the exception at the topmost level of that operation, to ensure that it doesn't continue.
If your program can work around that particular exception (perhaps by trying something else before giving up), take each layer of nested functions (starting from the highest) and each time ask yourself: If the exception occurs during the execution of some line of code in this function, would it make sense for this function to continue? As long as the answer is "yes", move to the deeper level. As soon the answer is "no", chances are this is the best place to put the handler for that exception.
Alternatively to the previous one, you could decide what would your program's alternate "plan of attack" be in case the exception is raised. Then, go to the line of code that would raise that exception and ask yourself: Does this function have enough context information to perform the workaround I have in mind? As long as the answer is "no", move to the caller function. As soon as the answer becomes "yes", consider putting your exception handler there.
That being said, you should only catch reasonably specialized exceptions and keep the catch(Exception ex) construct only as a last resort only at the top level and only after all the other possible catch blocks, reserving it only for kinds of exceptions you really couldn't predict at the time of writing. (I know you said this is not the point of the example, but since we're at it, I thought it should be mentioned to make this answer more complete.)
You should only catch those exceptions which you want to handle. You may include a topmost exception handler to turn any unhandled exceptions into something somewhat useful for the end user.
Instead of e.printStackTrace();, try return proper exception message.
find out more about exception handling here
Here is more discussion about exception handling.
AFAIK the best practice will be smth like that:
public void addVehicle(Vehicle vehicle) {
em.getTransaction().begin();
try {
em.persist(vehicle);
em.getTransaction().commit();
} catch (Exception e) {
if (em.getTransaction().isActive()) {
try {
em.getTransaction().rollback();
} catch (Exception e) {
// Log rollback failure or something
}
}
throw new RuntimeException(e);
}
}
Use both, the only reason is to use catch RuntimeException or even Throwable. Because this kind of exception is typically thrown by the underlying frameworks. An you should catch exactly this kind of exception if you want to make some actions, for example logging, print stack trace, etc., before you re-throw it again. If you don't do in such way you may loose the cause of exception.
#Transactional
public void addVehicle(Vehicle vehicle) {
try {
//do whatever with session
} catch (RuntimeException e) {
e.printStackTrace();
throw new Exception(e);
}
}