Here is the code:
public Response getABC(Request request) throws Exception {
Response res = new Response();
try {
if (request.someProperty == 1) {
// business logic
} else {
throw new Exception("xxxx");
}
} catch (Exception e) {
res.setMessage(e.getMessage); // I think this is weird
}
return res;
}
This program is working fine.
I think it should be redesigned, but how?
It makes no sense to throw an exception in a try block and immediately catch it, unless the catch block throws a different exception.
Your code would make more sense this way:
public Response getABC(Request request) {
Response res = new Response();
if (request.someProperty == 1) {
// business logic
} else {
res.setMessage("xxxx");
}
return res;
}
You only need the try-catch block if your business logic (executed when the condition is true) may throw exceptions.
If you don't catch the exception (which means the caller will have to handle it), you can do without the else clause:
public Response getABC(Request request) throws Exception {
if (request.someProperty != 1) {
throw new Exception("xxxx");
}
Response res = new Response();
// business logic
return res;
}
if you are throwing the exception from the method then why bother catching it ? it's either you return a response with "xxxx" message or throw an exception for the caller of this method to handle it.
public Response getABC(Request requst) {
Response res = new Response();
if(request.someProperty == 1){
//business logic
else{
res.setMessage("xxxx");
}
}
return res;
}
OR
public Response getABC(Request requst) throw Excetpions {
Response res = new Response();
if(request.someProperty == 1){
//business logic
else{
throw new Exception("xxxx");
}
return res;
}
public void someMethod(Request request) {
try {
Response r = getABC(request);
} catch (Exception e) {
//LOG exception or return response with error message
Response response = new Response();
response.setMessage("xxxx");
retunr response;
}
}
it doesn't seems right when purposely throwing exception and then directly catch it,
it can be redesign like this,
can change throw new Exception("xxxx"); with res.setMessage("xxxx");,
and then can keep the catching exception part in order to catch exception that may happen inside the business logic.
public Response getABC(Request requst) {
Response res = new Response();
try{
if(request.someProperty == 1){
//business logic
else{
res.setMessage("xxxx");
}
}catch(Exception e){
res.setMessage(e.getMessage);
}
return res;
}
First and foremost, tread more carefully when you refactor a working method - especially if you are performing a manual refactoring. That said, introducing a variable to hold message may be one way of changing the design:
public Response getABC(Request requst) throw Excetpions {
String message = "";
try{
if(request.someProperty == 1){
//business logic
else{
message = "xxxx";
}
}catch(Exception e){
message = e.getMessage();
}
Response res = new Response();
res.setMessage(message);
return res;
}
The assumption is that the business logic does it's own return when it succeeds.
I think you might be missing the point of that try/catch. The code is using the exception system to bubble any exception message to the caller. This could be deep inside a nested call stack--not just the one "throws" you are looking at.
In other words, the "throws" declaration in your example code is taking advantage of this mechanism to deliver a message to the client, but it almost certainly isn't the primary intended user of the try/catch. (Also it's a sloppy, kinda cheap way to deliver this message--it can lead to confusion)
This return value isn't a great idea anyway because Exceptions often don't have messages and can be re-wrapped... it's better than nothing though. Exception messages just aren't the best tool for this, but handling an exception at a high level like this is still a good idea.
My point is, if you refactor this code be sure to look for runtime exceptions that might be thrown anywhere in your code base (at least anywhere called during message processing)--and even then you should probably keep the catch/return message as a catch-all just in case a runtime exception pops up that you didn't expect. You don't have to return the error "Message" as the message of your response--It could be some quippy "We couldn't process your request at this time" instead, but be sure to dump the stack trace to a log. You are currently throwing it away.
Why did you use try/catch statement when you already throw Checked Exception?
Checked exception is usually used in some languages like C++ or Java, but not in new language like Kotlin. I personally restrict to use it.
For example, I have a class like this:
class ApiService{
Response getSomething() throw Exception();
}
which feels clean and readable, but undermines the utility of the exception handling mechanism. Practically, getSomething() doesn't offen throw checked exception but still need to behave as it does? This works when there is somebody upstream of ApiService who know how to deal with the unpredictable or unpreventable errors like this. And if you can really know how to deal with it, then go ahead and use something like the example below, otherwise, Unchecked Exception would be sufficient.
public Response getSomething(Request req) throws Exception{
if (req.someProperty == 1) {
Response res = new Response();
// logic
} else {
thows Exception("Some messages go here")
}
}
I will encourage to do in this way:
public Response getSomething(Request req){
if (req.someProperty == 1) {
Response res = new Response();
// logic
return res;
} else {
return ErrorResponse("error message"); // or throw RuntimeException here if you want to
}
}
For more insights, Kotlin which I mentioned before doesn't support Checked exception because of many reasons.
The following is an example interface of the JDK implemented by StringBuilder class:
Appendable append(CharSequence csq) throws IOException;
What does this signature say? It says that every time I append a string to something (a StringBuilder, some kind of a log, a console, etc.) I have to catch those IOExceptions. Why? Because it might be performing IO (Writer also implements Appendable)… So it results into this kind of code all over the place:
try {
log.append(message)
}
catch (IOException e) {
// Must be safe
}
And this is no good, see Effective Java, 3rd Edition, Item 77: Don't ignore exceptions.
Take a look at these links:
Checked and unchecked exception
Java's checked exceptions were a mistake (Rod Waldhoff)
The Trouble with Checked Exceptions (Anders Hejlsberg)
The exception mechanism has three purposes:
Immediately disable normal program flow and go back up the call stack until a suitable catch-block is found.
Provide context in form of the exception type, message and optionally additional fields that the catch-block code can use to determine course of action.
A stack trace for programmers to see to do forensic analysis. (This used to be very expensive to make).
This is a lot of functionality for a mechanism to have. In order to keep programs as simple as we can - for future maintainers - we should therefore only use this mechanism if we really have to.
In your example code I would expect any throw statement to be a very serious thing indicating that something is wrong and code is expected to handle this emergency somewhere. I would need to understand what went wrong and how severe it is before going on reading the rest of the program. Here it is just a fancy return of a String, and I would scratch my head and wonder "Why was this necessary?" and that extra effort could have been better spent.
So this code is not as good as it can be, but I would only change it if you had the time to do a full test too. Changing program flow can introduce subtle errors and you need to have the changes fresh in your mind if you need to fix anything.
Same if you want to get the specific exception message returned by JVM on failure, that time you can use the try-catch with methods getMessage() or printStackTrace() in the catch block. So here you can modify your code like :
public Response getABC(Request request) throws Exception {
Response res = new Response();
try {
if (request.someProperty == 1) {
// business logic
}
} catch (Exception e) {
res.setMessage(e.getMessage);
}
return res;
}
Related
Imagine some code:
public void doSomething(Object object){
try {
if (object == null)
throw new BusinessException("Object was null");
try {
// do logic actions
} catch (Exception e) {
throw new BusinessException("Something went wrong doing logic", e)
}
try {
// do some IO actions
} catch (Exception e) {
throw new BusinessException("Something went wrong doing IO.", e)
}
} catch(Exception e){
throw new BusinessException("Something went wrong in doSomething.", e)
}
}
The BusinessException is an extension of RuntimeException. I'm told by my manager and another senior engineer that BusinessException is the only exception that should ever get thrown and every method should be designed like the above method to ensure that. Anytime something goes wrong they want the same BusinessException thrown.
They idea is that they want to "abstract" away logical exceptions from the user and only provide "business exceptions" to the user. My manager does not want us to only catch specific exceptions, e.g. IOException They want to always catch(Exception) to make sure nothing is missed.
I don't understand this "abstraction" they are talking about. I'm pretty sure nothing is being "abstracted" away, an exception is just being encapsulated (or masked) in a new exception.
Semantics aside, I find this truly bizarre and I'm struggling to understand the value they think this verbose exception handling provides. It is not hard for me to imagine how this can make debugging more difficult. If any business exception gets thrown it immediately gets caught by another catch block and re-wrapped into a new exception, complicating the stack trace and potential debugging efforts.
It also seems like a performance issue to have so much exception instantiation.
Further, this is a spring boot application and we already have a ResponseEntityExceptionHandler
#ControllerAdvice
public class MyAppResponseEntityExceptionHandler extends ResponseEntityExceptionHandler{
#ExceptionHandler(value = { IllegalArgumentException.class })
protected ResponseEntity<Object> handleConflict(IllegalArgumentException ex, WebRequest request) {
String bodyOfResponse = "Check the arguments";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request);
}
// Several more for different exception types...
}
Is this just a "to each their own" situation or is this objectively a problem?
First of all, it's never recommended to have a generic catch block that catches and instance of Throwable or Exception, unless it exists in a chain of catch blocks, for example:
public void doSomething() {
try {
// do some database stuff
} catch (SQLException e) {
throw new BusinessException("something went wrong with database", e);
}
try {
// do some IO stuff
} catch (IOException e) {
throw new BusinessException("something went wrong with IO");
}
}
Now anything other than those two exceptions shouldn't be caught, since it's not the responsibility of this particular function, function should only complain about errors that are relative to what they do.
as a caller I might do something like this:
SomethingDoer s = new SomethingDoer();
s.doSomething();
now if I'm worried that an exception might get thrown unexpectedly, it's my responsibility as a caller to handle it, so the API deligates the uncaught exception for the caller to handle, like so:
SomethingDoer s = new SomethingDoer();
try {
s.doSomething();
} catch ( BusinessException e) {
LOGGER.error(e.message) // prod logging
LOGGER.debug(e) // debug logging with stacktrace
// hypothetical error listener
errorListener.onError(e);
//handle or log, but not rethrow.
} catch (Exception e) { // cringe..
LOGGER.error("something went wrong, unexpectedly"); // prod logs
LOGGER.debug("something went wrong, unexpectedly", e); // debug logs with stacktrace
/* logged AND rethrown since up till this point all expected
exceptions should be wrapped and rethrown or logged,
so if we get here its a fatal error, and you need to interrupt the application*/
throw e;
The latter - cringe looking - catch( Exception e) block is also not recommended and the exception should be propagated up the stack to the main thread, Checked Exceptions are usually handled that way.
So language specific exceptions - internal - should be caught and wrapped in a BusinessException even before reaching the ControllerAdvice handler and this handler - since it is relatively close to the view layer of the app should only handle business specific exceptions and not internal exceptions.
Your manager and senior engineer may be considering Effective Java. From the third edition, Item 73: Throw exceptions appropriate to the abstraction.
It is disconcerting when a method throws an exception that has no apparent connection to the task that it performs. This often happens when a method propagates an exception thrown by a lower-level abstraction. Not only is it disconcerting, but it pollutes the API of the higher layer with implementation details. If the implementation of the higher layer changes in a later release, the exceptions it throws will change too, potentially breaking existing client programs.
To avoid this problem, higher layers should catch lower-level exceptions and, in their place, throw exceptions that can be explained in terms of the higher-level abstraction. This idiom is known as exception translation.
Perhaps your manager is being overzealous with this bit of advice. Effective Java goes on to caution,
While exception translation is superior to mindless propagation of exceptions from lower layers, it should not be overused.
You may be justified in pointing out this overuse to your manager, but I suspect persuasion will be difficult. You can take some solace in Item 72: Favor the use of standard exceptions. I personally prefer that advice, and tend to avoid creating custom exceptions, but certainly other developers feel differently.
It is like, the end user doesn't know what to do with exception so a generic exception will be better.
You can write diff custom exceptions for diff type of operations, like Database calls, api calls and return only one type of exception to the caller.
i.e You can define you custom exception like this.
public class BusinessException extends RuntimeException {
private final ErrorCodes errorCode;
private final Object body;
public BusinessException(String message, ErrorCodes errorCode) {
super(message);
this.errorCode = errorCode;
this.body = null;
}
public BusinessException(String message, ErrorCodes errorCode, Object body) {
super(message);
this.errorCode = errorCode;
this.body = body;
}
}
Where ErrorCodes is the enum that will be having the ErrorCodes like InternalError, EntityNotFound, Unauthorised.
Now you can use this custom exception, you will catch any exception in the application and throw this exception with proper error message and error code.
Something like this.
throw new BusinessException("Error while fetching some api data.", INTERNAL_SERVER_ERROR);
or
throw new ServiceException("User is not authorised to perform operation.", UNAUTHORIZED);
I have a DBUtil class for jdbc, some method like query, insert and update, when some errors occur, we throw a RuntimeException now, but I have some questions.
When error occor, if I don't use try catch block to handle exception, I can't define whether it was succeed or not in code, so I can't do other things using the result, and controller will have no response rather than 500 error.
1:
try{
} catch(Exception e){
throw new RuntimeException("...")
}
2:
try{
} catch(Exception e){
log.error("..")
return someresult;// -1, empty list or others
}
so, which is better in code?
Thanks!
In any system not handling exceptions is not a good idea.
If you want centralized exception handling then
you can throw exceptions from multiple parts of application and handle in centralized class/controller
in such cases you can use
try{
} catch(Exception e){
throw new RuntimeException("...")
}
in catch you can have custom exception classes with proper message and all
If you want handle exceptions right away then you can try
try{
} catch(Exception e){
log.error("..")
return someresult;// -1, empty list or others
}
for e.g. if exception comes in try block you will be returning false otherwise true. Or null or blank message depends on implementation.
when you are re-throwing exception you can use finally to close resultsets/ open stream etc which is good practise
I think the best way is to create a custom exception class for your application.
Handle all your exception in one custom class. And handling method inside this class for all the exceptions occurred.
class CustomExc extends Exception{
CustomExc(String s){
super(s);
}
}
I have this code:
HttpPut put = new HttpPut(url);
try {
put.setEntity(new StringEntity(body, "UTF-8"));
} catch (UnsupportedEncodingException e1) {
// That would really not be good
e1.printStackTrace();
}
On a platform that is known to support that encoding.
The exception is never going to be raised. I will never do anything about it.
The fact that the code is there still suggests that there is a chance that it may happen, and that the rest of the code could be executed in an unreliable state. But it will never. Or if it does, graceful network connections fallback is the last of my problems.
So I have this ugly useless try catch block. What should I do with it?
(In this specific case, there is not much other choice if I want to use StringEntity. String.getBytes for example has a bunch of methods that would accept a Charset object, for instance, avoiding the need to catch the exception, but not StringEntity)
I would throw some kind of RuntimeException which indicates that you think this really should never happen. That way:
If it ever does happen, you find out about it rather than swallowing it and continuing
Your expectation that it really can never happen is clearly documented
You could even create your own subclass of RuntimeException for precisely this:
// https://www.youtube.com/watch?v=OHVjs4aobqs
public class InconceivableException extends RuntimeException {
public InconceivableException(String message) {
super(message);
}
public InconceivableException(String message, Throwable cause) {
super(message, cause);
}
}
You might also want to encapsulate the operation into a separate method, so that you don't get such catch blocks populating your code. For example:
public static HttpPut createHttpPutWithBody(String body) {
HttpPut put = new HttpPut(url);
try {
put.setEntity(new StringEntity(body, "UTF-8"));
return put;
} catch (UnsupportedEncodingException e) {
throw new InconceivableException("You keep using that encoding. "
+ "I do not think it means what you think it means.", e);
}
}
Then you can call createHttpPutWithBody wherever you'd need to, and keep your main code "catch clean".
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();
}
I have a function that loops while doing something that could throw an exception. Looks something like this:
public void myFunction() throws MyException {
while(stuff) {
try {
DoSomething() // throws an exception
}
catch (Exception ex) {
throw new MyException(some, stuff, of, mine, ex);
}
}
}
The error causing the exception is recoverable. It can be something like an SQL error in a single update statement where the while loop executes a series of update statements. Or a parsing error in a single piece of data, where the loop is processing multiple pieces of data. I need to pass the exception further up the chain so the GUI part of the program can process it, handle it and pass on the error to the user. But I don't want to kill the loop in this particular function. The other things it's doing might not be invalid. The error that caused the exception might not be fatal to the function.
So my question is this: Is it an acceptable practice to build linked lists of custom exceptions (where each exception is a node, and the exception thrown is the head of the list) and then throw the head of the list (if any) once the loop finishes?
Has anyone ever seen this done? Can anyone think of any potential problems with doing this? Can anyone think of other, better ways to handle the root problem: the need to pass up multiple unrelated exceptions with out exiting the function until it is done?
Here's an example of how the linking and throw might be implemented very simply:
public void myFunction() throws MyException {
MyException head = null;
while(stuff) {
try {
DoSomething() // throws an exception
}
catch (Exception ex) {
MyException tmp = new MyException(some, stuff, of, mine, ex);
tmp.next(head);
head = tmp;
}
}
if(head != null)
throw head;
}
My intial thought (other than I've not seen this) is that an exception is potentially quite a large object (containing the stacktrace) and I'd prefer not to store a lot of them.
I would instead build a list of the erroneous parameters/arguments as exceptions occur, and upon completion of the loop, throw a custom exception populated with this list (if the list has more than 0 elements). That would seem a more manageable way of handling this scenario.
public void myFunction() throws CustomException {
List<MyError> errors = new ArrayList<MyError>();
while(stuff) {
try {
DoSomething() // throws an exception
}
catch (Exception ex) {
errors.add(new MyError(some, stuff, of, mine, ex));
}
}
if (errors.size() > 0) {
throw new CustomException(errors);
}
}
Do you really need to throw all the exceptions? How do you expect to the individual, unrelated exceptions to be handled? Generally in cases like this, the system will just report the errors and be done with it.
If so, you might want to just collect the error messages and add them to a custom Exception class and throw that.
If those exceptions are really unrelated to each other so that you can't take benefit of get/setCause(), then I would rather collect this information in one MyException.
E.g.
public void myFunction() throws MyException {
MyException myException = null;
while(stuff) {
try {
DoSomething() // throws an exception
}
catch (Exception ex) {
if (myException == null) {
myException = new MyException();
}
myException.addException(some, stuff, of, mine, ex);
}
}
if (myException != null) {
throw myException;
}
}
Update: Brian handles exactly this approach in a more neat manner. I would opt for that instead :)
Actually throwing any exceptions from such a function is probably not the right way to handle this if it is expected that there will be errors. I'd suggest to either return a List (Array) of all exceptions/errors that occured or better to provide a error handler object to the function that can deal with the exceptions. i.e.:
public interface ErrorHandler
{
public void handleError( Throwable ex /*, add some context info */ );
}
public void myFunction( ErrorHandler eh )
{
while(stuff) {
try {
DoSomething() // throws an exception
}
catch (Exception ex) {
if( eh != null )
eh.handleError( ex );
}
}
}
This also lets the error handler either collect the errors to present them to the user or to decide that the whole batch operation has become void because of some error and to throw a exception of it's own to abort the processing early.
If the exception thrown by DoSomething(); could cause the very same method to throw another exception; this might be a problem. In other words, if DoSomething(); throws an exception because you didn't handle the previous one, there might be unnecesarry error to handle.
I think you can pass some callback or listener to the method, or set in a class variable and instead of a throw the list, like x4u did.
In Java there is an interface for this already: java.beans.ExceptionListener
IMO, an exception should be the last resource you have for handling an error. It should be avoided if possible. So, you might want to pass the error description (create error codes, pass the message, or something meaningful) to the GUI, and not the exception itself.