I have an annotation on a method M in which I am making some checks, if the checks doesn't succeed I do not want to execute the underlying method M. I want the caller to know that the call didn't succeed along with the reason.
To achieve this I am throwing an exception out of annotation if checks fails. So here I have a couple of questions:
I am unable to catch the specific exception because the IDE tells me that exception is not being thrown out of the method?
For a quick hack I am catching Exception and then get to the specific Exception by using instance of operator.
Is there any other better way to achieve this?
Do I have a way in which I need not throw the exception?
Annotation aspect code looks something like this:
#Before(value = "#annotation(abc)", argNames = "pjp, abc")
public Object around(ProceedingJoinPoint pjp, ABC abc) throws Throwable {
if(notAllow()){
throw new CustomException("Not allowed");
} else {
pjp.proceed()
}
}
}
The handler code looks something like this:
catch(Exception e){
if(e instanceof CustomException){
// do something
}
}
The IDE can only verify checked exceptions. Make the exception extend RuntimeException.
You can catch that any time you want, because the IDE cannot verify if any code throws it, since methods are not required to declare if they do.
Related
So im reading the below and i understand why you would do it..
https://jenkov.com/tutorials/java-exception-handling/exception-wrapping.html
example :
try{
dao.readPerson();
} catch (SQLException sqlException) {
throw new MyException("error text", sqlException);
}
So what if i want to isolate all external exceptions inside the dao layer only, and only use my exceptions. so in the above example i dont want to send SQLEXception inside the constructor, would doing the below be enough. Would it contain enough information :
throw new MyException("error text", sqlException);
or maybe my constructor should be the following instead
public MyException(String text,Exception ex)
You can inherit your exception from Exception like
MyException extends Exception {
}
and then use try catch like :
try {
dao.readPerson();
} catch (MyException ex) {
// handle Exception
}
by doing this you can do whatever you want in your class and i think its cleaner than other ways.
It will trigger automatically so you dont need to raise an exception.
If you want to catch SQL Exceptions only you can inherit MyException from SqlException so it will only trigger when SqlException happens
I understand that you worry about the catching part of your code knowing about the wrapped exception. In "not knowing" there are different layers.
Level 1: Nothing obligates the catching class to get the cause and therefor explicitly knowing about the SQLException. They just catch the MyException and don't care what's wrapped in it. Usually that's enough.
Level 2. Another level of not knowing is restricting the catching class to even have access to the wrapped exception. In that case why wrap it at all? Just catch the SQLException in your DAO layer and throw MyException without wrapping the original exception in it.
About wrapping the causing Exception instead of the original one. You could do that but you might lose valuable information so 99% of the time it's not recommended. There are some corner cases where I've done it though. Let's say you throwing code runs asynchronously through ExecutorService. Then if an exception is thrown it's wrapped to ExecutionException, but as a caller I might not be interested that the code ran asynchronously so I catch the ExecutionException, get it's cause (the actual exception that happened) and wrap that to my custom exception.
Consider following example. Is it considered a bad practise?
Note: I know re-throwing exception is ok, but what about assertionerror?
public static main(){
try {
doSmth();
} catch (WhateverException we) {
throw new AssertionError(e.getMessage());
}
}
public static void doSmth() throws WhateverException { }
It's not bad practice to throw an error in response to an exception, if the exception indicates a situation that is fatal for your code. However:
There's no need to use AssertionError in particular. I mean, it's fine if you do, since nobody's going to be catching one, but you should consider just doing Error instead, so that somebody doesn't go looking for the assert statement that they assumed caused it.
When chaining a throwable like that, always use the old exception to construct the new one: throw new AssertionError(we). That'll keep the old stack trace around. You can (and should) also pass a custom message.
Assume that we got an remote ejb which provides a asynchronous method with exception
#Stateless
public class MyBean {
...
#Asynchronous
public Future<Void> doSomething()
throws MyException
{
//implementation
}
...
}
Now the client side:
try {
Future<Void> result = myBean.doSomething()
}
catch(MyException e)
{
//Useless required catch block?
}
I know that the exception can be retrieved of the Future object when it is returned.
My question is if there is a better implementation without that useless empty catch block which will not be called anyway.
Another solution will be to make MyException to extend RunTimeException like this. Not sure if this is possible for you. Notice the annotaiton with rollback=false (Assuming you have a checked exception without rollback set to true). This way you don't have to mention it in the throws clause or catch it. The annotation will make sure that it will not be wrapped in EJBException.
#ApplicationException(rollback = false)
public class MyExcepton extends RuntimeException {
...
}
Indeed, if you throw your custom exception, then you decided that the calling code has to deal with it and you do so by catching it as with any synchronous method. And if you are saying, the catch block is useless, then the question is, why you throw the exception at all?
To avoid dealing with the exception in the client code, you may instead return an object holding the outcome of the call, which can then be an error that occurred. You still need to handle this situation, but you won't need a try-catch-block. See this post for an example.
Further reading: Java EE Tutorial.
I'm pondering on exception handling and unit tests best practices because we're trying to get some code best practices in place.
A previous article regarding best practices, found on our company wiki, stated "Do not use try/catch, but use Junit4 #Test(expect=MyException.class)", without further information. I'm not convinced.
Many of our custom exception have an Enum in order to identify the failure cause.
As a result, I would rather see a test like :
#Test
public void testDoSomethingFailsBecauseZzz() {
try{
doSomething();
} catch(OurCustomException e){
assertEquals("Omg it failed, but not like we planned", FailureEnum.ZZZ, e.getFailure());
}
}
than :
#Test(expected = OurCustomException.class)
public void testDoSomethingFailsBecauseZzz() {
doSomething();
}
when doSomethig() looks like :
public void doSomething throws OurCustomException {
if(Aaa) {
throw OurCustomException(FailureEnum.AAA);
}
if(Zzz) {
throw OurCustomException(FailureEnum.ZZZ);
}
// ...
}
On a side note, I am more than convinced that on some cases #Test(expected=blabla.class) IS the best choice (for example when the exception is precise and there can be no doubt about what's causing it).
Am I missing something here or should I push the use of try/catch when necessary ?
It sounds like your enum is being used as an alternative to an exception hierarchy? Perhaps if you had an exception hierarchy the #Test(expected=XYZ.class) would become more useful?
If you simply want to check that an exception of a certain type was thrown, use the annotation's expected property.
If you want to check properties of the thrown exception (e.g. the message, or a custom member value), catch it in the test and make assertions.
In your case, it seems like you want the latter (to assert that the exception has a certain FailureEnum value); there's nothing wrong with using the try/catch.
The generalization that you should "not use try/catch" (interpreted as "never") is bunk.
Jeff is right though; the organization of your exception hierarchy is suspect. However, you seem to recognize this. :)
If you want to check the raw exception type, then the expected method is appropriate. Otherwise, if you need to test something about the exception (and regardless of the enum weirdness testing the message content is common) you can do the try catch, but that is a bit old-school. The new JUnit way to do it is with a MethodRule. The one that comes in the API (ExpectedException) is about testing the message specifically, but you can easily look at the code and adapt that implementation to check for failure enums.
In your special case, you want to test (1) if the expected exception type is thrown and (2) if the error number is correct, because the method can thrown the same exception with different types.
This requires an inspection of the exception object. But, you can stick to the recommendation and verify that the right exception has been thrown:
#Test(expected = OurCustomException.class)
public void testDoSomethingFailsBecauseZzz() {
try {
doSomething();
} catch (OurCustomException e) {
if (e.getFailureEnum.equals(FailureEnum.ZZZ)) // use *your* method here
throw e;
fail("Catched OurCostomException with unexpected failure number: "
+ e.getFailureEnum().getValue()); // again: your enum method here
}
}
This pattern will eat the unexpected exception and make the test fail.
Edit
Changed it because I missed the obvious: we can make a test case fail and capture a message. So now: the test passes, if the expected exception with the expected error code is thrown. If the test fails because we got an unexpected error, then we can read the error code.
I came across this when searching how to handle exceptions.
As #Yishai mentioned, the preferred way to expect exceptions is using JUnit rules and ExpectedException.
When using #Test(expected=SomeException.class) a test method will pass if the exception is thrown anywhere in the method.
When you use ExpectedException:
#Test
public void testException()
{
// If SomeException is thrown here, the test will fail.
expectedException.expect(SomeException.class);
// If SomeException is thrown here, the test will pass.
}
You can also test:
an expected message: ExpectedException.expectMessage();
an expected cause: expectedException.expectCause().
As a side note: I don't think using enums for exception messages/causes is good practice. (Please correct me if I'm wrong.)
I made catch-exception because I was facing the same problem as you did, Stph.
With catch-exception your code could look like this:
#Test
public void testDoSomethingFailsBecauseZzz() {
verifyException(myObj, OurCustomException.class).doSomething();
assertEquals("Omg it failed, but not like we planned", FailureEnum.ZZZ,
((OurCustomException)caughtException()).getFailure() ;
}
I'm reading exception handling in the book "A programmer guide to Java SCJP certificate". The author wrote that :
If a checked exception is thrown in a method, it must be handled in one of three ways:
1.By using a try block and catching the exception in a handler and dealing with it
2.By using a try block and catching the exception in a handler, but throwing
another exception that is either unchecked or declared in its throws clause
3.By explicitly allowing propagation of the exception to its caller by declaring it
in the throws clause of its method header
I understood clearly the first and third, but the second made me a lot of confused. My concerns are that :
-It's still alright even if I don't throw any other unchecked exceptions, so why do we have to throw another exception at here?
-Why do we have to re-declare the exception that we have caught, in throws clause? I think it's over by the handler.
Thanks to everyone.
The book just list three allowed options.
-It's still alright even if I don't throw any other unchecked exceptions,
so why do we have to throw another
exception at here?
You might want to throw another more descriptive exception, for example adding more info.
-Why do we have to re-declare the exception that we have caught, in
throws clause? I think it's over by
the handler.
You don't have to re-declare. But if the new exception you are throwing is checked, then you must declare it in the throws clause. In fact the exception you just caught doesn't need to be declared even if checked.
You may want to do this to catch a checked exception and throw another checked exception of a different kind. Perhaps you want to throw your own exception rather than a different one.
public void doSomething() throws MyCheckedException {
try {
doSomethingThatThrowsSpecificCheckedException();
} catch(SpecificCheckedException e) {
throw new MyCheckedException();
}
}
Or you can throw an unchecked exception (something that is or extends RuntimeException).
public void doSomething() {
try {
doSomethingThatThrowsSpecificCheckedException();
} catch(SpecificCheckedException e) {
throw new RuntimeException();
}
}
First of all, you should declare in the throw clause the exception that you throw, not the one you caught, assuming you are throwing a checked exception.
Second, you don't have to do that. It is just one of the three options.
Why would you do that? Usually this is done between the application layers. For example, Hibernate catches SQLExceptions and rethrows them as unchecked HibernateException, so that code that calls Hibernate methods doesn't have to be polluted with the try/catches for SQLExceptions. Another option is to translate a low-level exception into some business logic exception that can be handled up the stack. This allows for the better isolation of the business logic from the low level implementation details.
Great question, and one which good java programmers should get their head around.
It's all about adhering to the method signature that defines the method's contract with its caller, and which includes what exceptions you are going to throw.
Option 1 is dealing with the exception
Option 2 is not dealing with the exception, but keeping the same contract
Option 3 is not dealing with the exception and changing your contract
A implementation of the pattern in option 2 would be:
public interface Server {
public void useServer() throws ServerException;
}
public class ExplodingClient {
private Server server = new ServerImpl();
public void doIt() throws ClientException {
try {
server.useServer();
} catch (ServerException e) {
// Our contract doesn't allow throwing ServerException,
// so wrap it in an exception we are allowed by contract to throw
throw new ClientException(e);
}
}
}
public class SilentClient {
private Server server = new ServerImpl();
public void doIt() {
try {
server.useServer();
} catch (ServerException e) {
// Our contract doesn't allow throwing any Exceptions,
// so wrap it in a RuntimeException
throw new RuntimeException(e);
}
}
}
By using a try block and catching the
exception in a handler, but throwing
another exception that is either
unchecked or declared in its throws
clause.
Handling the exception in Java can be done in two ways :
Wrapping it in try-catch-finally block.
Declaring the method to throw ( using throws) the exception to the caller of method to handle.
-It's still alright even if I don't throw any other unchecked exceptions,
so why do we have to throw another
exception at here?
Throwing another exception means describing more about it. Also, to let the caller of the method know that this particular exception was generated.
-Why do we have to re-declare the exception that we have caught, in
throws clause? I think it's over by
the handler.
Redeclaring exception that you just caught in the catch block is to make the caller of this method alert that this method could throw a particluar exception. So be prepare to handle it.
You must go over this Jon Skeet's post : Sheer Evil: Rethrowing exceptions in Java
Remember, you are never forced to handle the unchecked exceptions, compiler forces you to just catch the checked one.