I need to implement Exception management component, in Java.
Having this class :
public class Foo {
void connect(){
// some instructions here...
}
}
The specification document that I have it uses such expressions :
1. A_Exception can be received.
2. B_Exception can be catched as C_Exception<B_Exception> .
Edit :
What is the difference between a catched exception and a received exception? Some sample codes would be so helpful.
Thank you a lot!
Exception what will going to be handle is depends on the context. Importantly Checked Exception can be handle. You have to provide the context for this case. Normally NullPointerException not going to handle and will code the way not occur NPE.
Related
My understanding of these exceptions is if an object in the database that you are looking for doesn't exist or exists these gets thrown? But is it ok for myself to use when I want to handle different cases in MyServiceClass.
Is it bad practice to throw these exceptions or should I create my own Exceptions for let's say if a user dont exist in the database?
How does it work in a real production?
Thanks in advance!
You should only implement a custom exception if it provides a benefit compared to Java's standard exceptions. The class name of your exception should end with Exception.
But it’s sometimes better to catch a standard exception and to wrap it into a custom one. A typical example for such an exception is an application or framework specific business exception. That allows you to add additional information and you can also implement a special handling for your exception class.
When you do that, make sure to set the original exception as the cause. The Exception class provides specific constructor methods that accept a Throwable as a parameter. Otherwise, you lose the stack trace and message of the original exception which will make it difficult to analyze the exceptional event that caused your exception.
public void wrapException(String input) throws MyBusinessException {
try {
// do something
} catch (NumberFormatException e) {
throw new MyBusinessException("A message that describes the error.", e);
}
}
Try not to create new custom exceptions if they do not have useful information for client code.
And if you make a custom exception be sure to:
Document the Exceptions You Specify
Throw Exceptions With Descriptive Messages
Catch the Most Specific Exception First
Don’t Log and Throw
I have service, a simple class that need to take input and run some business logic. Before executing this service, the user must set all the data. In general, it look like this:
public class TestService extends InnerServiceBase {
/**
* Mandatory input
*/
private Object inputObj;
#Override
protected ErrorCode executeImpl() {
//Some business logic on inputObj
return null;
}
public void setInputObj(Object inputObj) {
this.inputObj = inputObj;
}
}
What is the best runtime exception to throw in case the inputObj is null ?
IllegalStateException seems like the best fit. The object is not in the correct state to have executeImpl() called on it. Whatever exception you use, make sure the error message is helpful.
Whether you should be using an unchecked exception at all is a whole other question...
Depends on the scenario.
If this is part of an API that another developer is using, throwing NullPointerException is reasonable since you don't want that input to be null. Adding a descriptive exception message would be helpful.
If you're not interested in throwing an NPE, or this is part of code that's not going into an API, then you could throw an IllegalArgumentException, as null could be considered an illegal argument.
If setInputObj is called with a null argument, and that's not valid, then throw NullPointerException. There's some debate over the "correct" exception here (IllegalArgumentException or NullPointerException for a null parameter?), but Guava, Apache Commons Lang and even the JDK itself (Objects.requireNonNull) have settled on NPE.
If executeImpl is called before inputObj has been set, throw IllegalStateException.
I'm implementing a session bean that throws ApplicationExceptions.
These exceptions have chained stack traces that may contain exceptions whose classes aren't available on the client. Something like:
#Override
public void doSomethingSpecial(MyObject o) throws MyException {
try {
legacySystem.handle(o);
} catch (LegacyException e) {
logger.warn(e.getMessage(), e);
throw new MyException(e);
}
}
Here it's possible that the client gets an exception it doesn't have the class for. This can result in:
Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
at sun.proxy.$Proxy0.doSomethingSpecial(Unknown Source)
at com.myapp.client.Client.main(Client.java:56)
Caused by: java.lang.ClassNotFoundException: MyLegacyException
I don't want the client to know all the possible exceptions that can be thrown on the server side, but having a stack trace is never bad.
How do you handle these problems? Is it a passable solution to implement an Interceptor that decouples the stack trace when the exception is sent back to the client? But then the Interceptor should handle only calls via the RemoteInterface, because internally I'm interested in the whole stack trace.
It depends on your client type. If a client is another team which is developing another component or subsytem, I'm agree with you about:
Having a stack trace is never bad
But if they are customers who have no idea about your application internals, so there is no reason for them to know your exception classes or even see your stack traces. It would be nice to have a protocol which force you to catch all exceptions and wrap them in a high level exception class with a error_code property. This way, you can have a specific error code for each catch statement in your application and you will give your clients a list of these codes.
Anyway, from technical view, if your clients doesn't have access to your internal Exception classes, so they can't have access to your stack trace without referred ClassNotFoundException. If you really want them to see the stack trace, one solution could be to have an Aspect which sits just on the most upper layer of your API (which is going to be called by clients) and catches all the exceptions, writes their stack traces in a String and sends this as a property of the final exception which is going to be caught by caller. This way, the caller can access the stack trace as a formatted String property of the exception.
Edit:
You can even configure your build script, so that this Aspect never be a part of your release versions. So you can give this stack trace messages just in your debug version.
I thought about little roundabout solution, but this is only untested speculation.
You initialize your external exception with internal exception. But if we look at javadoc of Throwable we can see methods get and setStackTrace(StackTraceElement[] stackTrace)
StackTraceElement is initialized with strings. So maybe you can get stack trace from internal exception and set it into your external exception (MyException).
Since RMI settles on Serialization you can use Serialization features to conditionally replace exceptions.
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
public class CarryException extends RuntimeException implements Serializable
{
final String exceptionClass;
public CarryException(Exception cause)
{
super(cause.getMessage());
exceptionClass=cause.getClass().getName();
setStackTrace(cause.getStackTrace());
}
#Override
public String getMessage()
{
// if we get here, reconstructing the original exception did not work
return exceptionClass+": "+super.getMessage();
}
/** Invoked by Serialization to get the real instance */
final Object readResolve() throws ObjectStreamException
{
try
{
Exception ex = Class.forName(exceptionClass).asSubclass(Exception.class)
.getConstructor(String.class).newInstance(super.getMessage());
ex.setStackTrace(getStackTrace());
return ex;
}
catch(InstantiationException|IllegalAccessException|ClassNotFoundException
| IllegalArgumentException|InvocationTargetException|NoSuchMethodException
| SecurityException ex)
{
// can't reconstruct exception on client side
}
return this; // use myself as substitute
}
}
Now you can throw any exception to the client by throw new CarryException(originalException);. The CarryException will always record the stack trace and message of the original exception and recreate the original exception at client side if the class is available. Otherwise the client sees the CarryException so obviously that one exception type must be known on the the client side.
The exception type must have the standard constructor taking a message String for the reconstruction to work. (All other things would be too complicated). But most exception types have that.
There is another catch: replacing via Serialization does only work if Serialization is involved so you must not invoke the methods on the implementation class directly when beeing inside the same JVM. Otherwise you see the CarryException unconditionally. So you have to use a stub even locally, e.g.
((MyRemoteInterface)RemoteObject.toStub(myImplementation)).doSomethingSpecial();
Update
If MyException is known to the client and only LegacyException is not, of course the following works:
catch (LegacyException e) {
logger.warn(e.getMessage(), e);
MyException me=new MyException(e.toString());
me.setStackTrace(e.getStackTrace());
throw me;
}
For example, i created a exception that extends RuntimeException.
My exception has a new field called "code". I want to handle this exception in Oracle Service Bus process and retrieve this code to throws another exception with a XML structure that includes the code.
Is there a way to do that ?
I don't think that you will be able to retrieve just the "code". But certainly you can retrieve the details of the exception which will include your code.
Try it out.
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() ;
}