Catch subclass of exception AND Exception in camel route - java

I have a camel route that I am using my own route builder to listen for the specific types of exceptions that I have created in my code.
so to my route, I have added
onException();
onMyTypeException();
I have also created the corresponding methods in my route builder
public OnExceptionDefinition onException(){
return onException(Exception.class)
....
public OnExceptionDefinition onMyTypeException(){
return onException(MyTypeException.class)
....
The problem is, onException() seems to catch everything, instead of letting me catch the more specific error first. The idea here being that in my system I have not accounted for every type of error, so if some get by, catch them in the onException()
Any ideas?

Camel will look for the explicit exception match first...but I think your initialization of the clauses is the issue. you shouldn't need to return them in your methods, etc...
overall, make sure you define your onException() clauses in the RouteBuilder's configure() method before any routes are setup...
see this page for more details...something like this...
public void configure() throws Exception {
onException(Exception.class).handled(true).log("general exception!!!");
onException(MyException.class).handled(true).log("my exception!!!");
from("direct:start").to("bean:myBean");
...
}

You can read overall about error handling with Camel here
http://camel.apache.org/error-handling-in-camel.html
And for using onException (which is also called exception clause) there is documentation here: http://camel.apache.org/exception-clause.html
However error handling in Camel is very flexible and elaborate. And also dealing and handling errors in integration use-cases is often hard. That is why we have devoted a full chapter in the Camel in Action book to cover this extensively. So if you got the book, then make sure to read chapter 5, it will help you a lot.

Related

Should exceptions be used to describe user input errors?

I have a service that saves a tree-like structure to a database. Before persisting the tree, the tree gets validated, and during validation, a number of things can go wrong. The tree can have duplicate nodes, or a node can be missing an important field (such as its abbreviation, full name, or level).
In order to communicate to the service what went wrong, I'm using exceptions. When the validateTree() method encounters a problem, it throws the appropriate exception. The HttpService class then uses this exception to form the appropriate response (e.g. in response to an AJAX call).
public class HttpService {
private Service service;
private Logger logger;
// ...
public HttpServiceResponse saveTree(Node root) {
try {
service.saveTree(root);
} catch (DuplicateNodeException e) {
return HttpServiceResponse.failure(DUPLICATE_NODE);
} catch (MissingAbbreviationException e) {
return HttpServiceResponse.failure(MISSING_ABBREV);
} catch (MissingNameException e) {
return HttpServiceResponse.failure(MISSING_NAME);
} catch (MissingLevelException e) {
return HttpServiceResponse.failure(MISSING_LEVEL);
} catch (Exception e) {
logger.log(e.getMessage(), e. Logger.ERROR);
return HttpServiceResponse.failure(INTERNAL_SERVER_ERROR);
}
}
}
public class Service {
private TreeDao dao;
public void saveTree(Node root)
throws DuplicateNodeException, MissingAbbreviationException, MissingNameException, MissingLevelException {
validateTree(root);
dao.saveTree(root);
}
private void validateTree(Node root)
throws DuplicateNodeException, MissingAbbreviationException, MissingNameException, MissingLevelException {
// validate and throw checked exceptions if needed
}
}
I want to know, is this a good use of exceptions? Essentially, I'm using them to convey error messages. An alternative would be for my saveTree() method to return an integer, and that integer would convey the error. But in order to do this, I would have to document what each return value means. That seems to be more in the style of C/C++ than Java. Is my current use of exceptions a good practice in Java? If not, what's the best alternative?
No, exceptions aren't a good fit for the validation you need to do here. You will likely want to display multiple validation error messages, so that the user can see all the validation errors at once, and throwing a separate exception for each invalid input won't allow that.
Instead create a list and put errors in it. Then you can show the user the list of all the validation errors.
Waiting until your request has gotten all the way to the DAO seems like the wrong time to do this validation. A server-side front controller should be doing validation on these items before they get passed along any farther, as protection against attacks such as injection or cross-site scripting.
TL;DR The Java-side parts you showed us are nearly perfect. But you could add an independent validation check and use that from the client side before trying to save.
There are many software layers involved, so let's have a look at each of them - there's no "one size fits all" answer here.
For the Service object, it's the perfect solution to have it throw exceptions from the saveTree() method if it wasn't able to save the tree (for whatever reason, not limited to validation). That's what exceptions are meant for: to communicate that some method couldn't do its job. And the Service object shouldn't rely on some external validation, but make sure itself that only valid data are saved.
The HttpService.saveTree() should also communicate to its caller if it couldn't save the tree (typically indicated by an exception from the Service). But as it's an HTTP service, it can't throw exceptions, but has to return a result code plus a text message, just the way you do it. This can never contain the full information from the Java exception, so it's a good decision that you log any unclear errors here (but you should make sure that the stack trace gets logged too!), before you pass an error result to the HTTP client.
The web client UI software should of course present detailed error lists to the user and not just a translated single exception. So, I'd create an HttpService.validateTree(...) method that returns a list of validation errors and call that from the client before trying to save. This gives you the additional possibility to check for validity independent of saving.
Why do it this way?
You never have control what happens in the client, inside some browser, you don't even know whether the request is coming from your app or from something like curl. So you can't rely on any validation that your JavaScript (?) application might implement. All of your service methods should reject invalid data, by doing the validation themselves.
Implementing the validation checks in a JavaScript client application still needs the same validation inside the Java service (see above), so you'd have to maintain two pieces of code in different languages doing exactly the same business logic - don't repeat yourself! Only if the additional roundtrip isn't tolerable, then I'd regard this an acceptable solution.
Visible and highly noticeable, both in terms of the message itself and how it indicates which dialogue element users must repair.
From Guru Nielsen,
https://www.nngroup.com/articles/error-message-guidelines/

Camel Idempotent removeOnFailure for some exception types only

Considering this simple Camel route:
from("timer:some timer")
.bean(someBeanThatProducesLists)
.split(body()).parallelProcessing() .
.idempotentConsumer(simple("${body.id}"), myIdempotentRepository)
.bean(beamThatProcesses)
This is working as expected. When an exception occurs in beamThatProcesses the key is removed and is re-processed if someBeanThatProducesLists returns an entry with the same ID again.
What I would like is to have
onException(MyCustomException.class)
.maximumRedeliveries(3)
And keep the ID in the idempotent repository after the re-deliveries are exhausted, but only for this specific exception, so removeOnFailure doesn't really help here.
I browsed through the documentation and also Camel In Action second edition v12, but could not find any way to implement this. I did find that marking exception handled does not help.
I could set removeOnFailure to false, and then have custom exception handlers that remove it in most exceptions and keep it on custom when retries exhausted, but it's error prone as the idempotent key would have to be computed in multiple places, exceptions can occur anywhere in the route etc.
I guess I could catch the exception in beamThatProcesses and deal with it there, but I'm hoping there is a way to instruct camel to do it.
I ended up implementing something like this in my idempotent repository:
#Override
public boolean remove(Exchange exchange, Object key) {
Throwable caught = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Throwable.class);
if (exchange.getException() == null && caught != null) {
logger.info("Exception was handled, not removing key");
return false;
} else {
// ... remove the message
}
}
You can use handled(true) for that specific onException to tell Camel that its okay, so the idempotent repository will see it as okay and do a commit and therefore store the id in the repository.
The handled(true) can also accept a Predicate so you can evaluate either true or false if you need even more fine grained control whether to handle or not.

Record instantiation of java.lang.Throwable transparently [duplicate]

How can I detect when an Exception has been thrown anywhere in my application?
I'm try to auto-magically send myself an email whenever an exception is thrown anywhere in my Java Desktop Application. I figure this way I can be more proactive.
I know I could just explicitly log and notify myself whenever an exception occurs, but I'd have to do it everywhere and I might(more likely will) miss a couple.
Any suggestions?
You probobly don't want to mail on any exception. There are lots of code in the JDK that actaully depend on exceptions to work normally. What I presume you are more inerested in are uncaught exceptions. If you are catching the exceptions you should handle notifications there.
In a desktop app there are two places to worry about this, in the event-dispatch-thread (EDT) and outside of the EDT. Globaly you can register a class implementing java.util.Thread.UncaughtExceptionHandler and register it via java.util.Thread.setDefaultUncaughtExceptionHandler. This will get called if an exception winds down to the bottom of the stack and the thread hasn't had a handler set on the current thread instance on the thread or the ThreadGroup.
The EDT has a different hook for handling exceptions. A system property 'sun.awt.exception.handler' needs to be registerd with the Fully Qualified Class Name of a class with a zero argument constructor. This class needs an instance method handle(Throwable) that does your work. The return type doesn't matter, and since a new instance is created every time, don't count on keeping state.
So if you don't care what thread the exception occurred in a sample may look like this:
class ExceptionHandler implements Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
handle(e);
}
public void handle(Throwable throwable) {
try {
// insert your e-mail code here
} catch (Throwable t) {
// don't let the exception get thrown out, will cause infinite looping!
}
}
public static void registerExceptionHandler() {
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());
System.setProperty("sun.awt.exception.handler", ExceptionHandler.class.getName());
}
}
Add this class into some random package, and then call the registerExceptionHandler method and you should be ready to go.
The new debugging hooks in Java 1.5 let you do this. It enables e.g. "break on any exception" in debuggers.
Here's the specific Javadoc you need.
Check out Thread.UncaughtExceptionHandler. You can set it per thread or a default one for the entire VM.
This would at least help you catch the ones you miss.
If you're using a web framework such as Spring then you can delegate in your web.xml to a page and then use the controller to send the email. For example:
In web.xml:
<error-page>
<error-code>500</error-code>
<location>/error/500.htm</location>
</error-page>
Then define /error/500.htm as a controller. You can access the exception from the parameter javax.servlet.error.exception:
Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception");
If you're just running a regular Java program, then I would imagine you're stuck with public static void main(String[] args) { try { ... } catch (Exception e) {} }
If you are using java 1.3/1.4, Thread.UncaughtExceptionHandler is not available.
In this case you can use a solution based on AOP to trigger some code when an exception is thrown. Spring and/or aspectJ might be helpful.
In my current project I faced the similar requirement regarding the errors detection. For this purpose I have applied the following approach: I use log4j for logging across my app, and everywhere, where the exception is caught I do the standard thing: log.error("Error's description goes here", e);, where e is the Exception being thrown (see log4j documentation for details regarding the initialization of the "log").
In order to detect the error, I use my own Appender, which extends the log4j AppenderSkeleton class:
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
public class ErrorsDetectingAppender extends AppenderSkeleton {
private static boolean errorsOccured = false;
public static boolean errorsOccured() {
return errorsOccured;
}
public ErrorsDetectingAppender() {
super();
}
#Override
public void close() {
// TODO Auto-generated method stub
}
#Override
public boolean requiresLayout() {
return false;
}
#Override
protected void append(LoggingEvent event) {
if (event.getLevel().toString().toLowerCase().equals("error")) {
System.out.println("-----------------Errors detected");
this.errorsOccured = true;
}
}
}
The log4j configuration file has to just contain a definition of the new appender and its attachement to the selected logger (root in my case):
log4j.rootLogger = OTHER_APPENDERS, ED
log4j.appender.ED=com.your.package.ErrorsDetectingAppender
You can either call the errorsOccured() method of the ErrorsDetectingAppender at some significant point in your programs's execution flow or react immidiately by adding functionality to the if block in the append() method. This approach is consistent with the semantics: things that you consider errors and log them as such, are detected. If you will later consider selected errors not so important, you just change the logging level to log.warn() and report will not be sent.
In this case I think your best bet might be to write a custom classloader to handle all classloading in your application, and whenever an exception class is requested you return a class that wraps the requested exception class. This wrapper calls through to the wrapped exception but also logs the exception event.
I assume you don't mean any Exception but rather any uncaught Exception.
If this is the case this article on the Sun Website has some ideas. You need to wrap your top level method in a try-catch block and also do some extra work to handle other Threads.
Sending an email may not be possible if you are getting a runtime exception like OutOfMemoryError or StackOverflow. Most likely you will have to spawn another process and catch any exceptions thrown by it (with the various techniques mentioned above).
There is simply no good reason to be informed of every thrown exception. I guess you are assuming that a thrown exception indicates a "problem" that your "need" to know about. But this is wrong. If an exception is thrown, caught and handled, all is well. The only thing you need to be worried about is an exception that is thrown but not handled (not caught). But you can do that in a try...catch clause yourself.

Java, return new MyException: anti-pattern?

In my class I'm doing validation of custom data. Many conditions apply. Upon any failure, I want to throw a specific MyException. Throwing this MyException takes many common parameters, and one custom parameter (based upon the actual failure). So an actual throw takes many characters to write and destroys tidyness because of code duplication. Also I have to throw it too much times. I made up my mind to create a private method that prepares and returns a new instance of this MyException and takes the only custom data as parameter, so the code can be much cleaner.
private MyException createMyException(final CustomErrorData errorData)
{
... some info gathering, parameterizing, etc...
return new MyException(errorData);
}
...
So throwing a new MyException is much shorter:
throw createMyException(errorData);
My question is: what's the correct practice to prevent code duplication in this case? I may be overmistifying Exceptions.
An Exception factory - never seen it before but at least it sounds like a proper design.
I just worry - you seem to put quite a lot effort on designing an exception throwing framework: adding parameters, states, etc. to exceptions. Do you really encounter that many exceptional conditions in your code? Or do you throw exceptions where proper handling of expected conditions would?
Usually a thrown exception is "just for the logs". Something happened that shouldn't have happened in the current context. Something, the developers should know and correct in the next release. We shouldn't use exceptions to handle expected states.
So before investigating in brilliant exception creation code, double-check if it's worth the effort or if the design of your application is starting to get ... too creative.
If you have one general type of exception you will lose some of the advantages of OOP.
Instead of being able to have try-catch for specific exception types you will have to have a catch for your general exception and then continue processing based on some fields inside your MyException class.
You will have something like this:
try{
//code here
}
catch (MyException ex){
switch(ex.exceptionType){
case IOException: doSomething();break;
case ConnectionException:doSomethingElse();break;
default: //throw the exception outwards if you don't want to process it
}
}
When instead you should have something like
try{
//code here
}
catch (IOException ex){
doSomething();
}
catch (ConnectionException ex){
doSomethingElse();
}
which is more clear and more OOP.
Why you would place all your exceptions under a general type is something of a puzzle, it's like making all your objects to be instances of only one class, but you would require of them different behaviors based on some flags.
Imho your helper function is perfectly fine, i dont see another approach that would be preferable here..
I would throw the exception in the method, unless this confuses the compiler.
private void throwMyException(final CustomErrorData errorData) {
... some info gathering, parameterizing, etc...
throw new MyException(errorData);
}
throwMyException(errorData);
or
private MyException throwMyException(final CustomErrorData errorData) {
... some info gathering, parameterizing, etc...
throw new MyException(errorData);
}
throwMyException(errorData);
// or if the compiler complains
throw throwMyException(errorData);
I'd separate the two concerns. Your class knows how to info gather, but shouldn't have to know about the exception (the user of that info).
First define a method to create a CustomErrorData instance:
private CustomErrorData createCustomErrorData() {
// info gathering
return new CustomErrorData(something);
}
Then define a constructor for the exception that uses a CustomErrorData:
public MyException(CustomErrorData errorData) {
// save it as a field
}
then
throw new MyException(createCustomErrorData());
where you need it.
This also allows you to use CustomErrorData for something else, perhaps logging, displaying to the user, whatever.

How do you customize exception handling behavior in JUnit 3?

I want to implement exception checking (like in JUnit 4) using JUnit 3. For example, I would like to be able to write tests like this:
public void testMyExceptionThrown() throws Exception {
shouldThrow(MyException.class);
doSomethingThatMightThrowMyException();
}
This should succeed if and only if a MyException is thrown.
There is the ExceptionTestCase class in JUnit, but but I want something that each test* method can decide to use or not use. What is the best way to achieve this?
Would the solution:
public void testMyExceptionThrown() throws Exception {
try {
doSomethingThatMightThrowMyException();
fail("Expected Exception MyException");
} catch(MyException e) {
// do nothing, it's OK
}
}
be suitable for what you're thinking of?
Also have a look at this thread, where someone created a Proxy-solution for JUnit3 which seems to be another possibility to solve your problem.
There is no need to implement your own solution because there is already one that can be used with JUnit3 (and any other testing framework): catch-exception.
The simplest approach is to use the Execute Around idiom to abstract away the try-catch that you would usually write.
More sophisticated is to note that TestCase is just a Test. I forget the details, but we can override the execution of the test (which the framework initially calls through run(TestResult) specified in Test). In that override we can place the try-catch, as per Execute Around. The testXxx method should call a set method to install the expected exception type.

Categories

Resources