First off, for anyone out there who abhors, detests and despises the instanceof operator, I understand your concerns with it, but am stuck using it. That's because I don't have the authority to completely refactor the way another development team set a project up, so unless I'm missing somethin here, I just don't see any way of avoiding it.
I have a Java POJO that cannot be changed, and allows you to set an Exception as one of its properties:
public class Message {
private Exception exception;
public void setException(Exception exc) {
this.exception = exc;
}
}
Again, I can't change this Message class.
I am writing an error handler method that gets passed a MessageContainer instances, and I need logic to do different things depending on what type of exception was set on the container's Message:
public class ErrorHandler {
public void handle(MessageContainer container) {
Message msg = container.getMessage();
Exception exc = msg.getException();
if(exc instanceof FizzException)
System.out.println("Do x");
else if(exc instanceof BuzzException)
System.out.println("Do y");
else
System.out.println("Do z");
}
}
Again, I can't change the fact that ErrorHandler#handle is passed a MessageContainer and not an injectable Message instance.
So, even though I really don't like to use instanceof, I don't see any other way of accomplishing this logic (but by all means, please make suggestions...as long as they don't involve making changes to Message, MessageContainer, or the handle(MessageContainer) method!).
But even with using instanceof, how does this code even work? Once you pull the Exception out of the Message, I don't think any of the instanceofs will fire, because its cast to an Exception, with no way to detect if it's BuzzException, FizzException, etc. What are my options here? Thanks in advance.
This code will work as expected. During runtime, instanceof statements will compare the actual type of exc, and not just assume this is only an Exception. If the only statement that worked was exc instanceof Exception, instanceof would be totally worthless :)
Another solution (which I would avoid to use) would be to compare fully qualified class names:
String fqcn = exc.getClass().getName();
if (fqcn.equals("com.foo.FizzException") {
// etc.
}
The cast to exception on
Exception exc = msg.getException();
does not erase the exception runtime type. It has merely cast it to a base type. The instanceof will still work. However, if your FizzException extends BuzzException, then you will need to do the instanceof checks in the other order. i.e. check for the most derived type first.
Otherwise, it will go into the base class check clause instead of the derived one.
It's not clear what you want. If the exceptions are all "given" and you can't change their implementations then you can use exception.getClass().getName() to get the class name and, maybe, look it up in a table or whatever to pick your course of action.
If you can change many of the exception implementations have them all implement an interface that provides a "functionality()" method or whatever. If an given Exception object is instanceof MyFunctionalityInterface then cast to MyFunctionalityInterface and call functionality() to have it return the info you need to guide your actions. Then use instanceof or getClass().getName() to manage the Exception classes you can't change.
Related
In a flow I've designed, I have a Validation component with a custom validator that references a class, DataValidator, implementing the mule Validator interface. In the DataValidator, I validate several properties and would like to throw different kinds of exceptions (possibly custom exceptions, created by me) for each one. Is this possible?
My understanding is that, by specifying the exceptionClass, the Validation component will only throw exceptions of that class.
There's the option to use an ExceptionFactory instead of an exceptionClass.
Does using it allows throwing several types of exception? If so, how can I use it? I checked this blog
post, but didn't understand it well enough.
In the case that none of this is possible, is there any way I can get the ValidationResult message in the custom validator component, so that I can use it in the message?
Yes you can throw several types of exceptions. As you mentioned, you'll have to implement the DataValidator and ExceptionFactory interface and configure your component to use them.
With Studio, choose "Use Exception Factory Config" and specify the full class name you want to use. With XML, specify the exception-factory you implemented in your validation-config. (You can also configure a Spring Bean and reference it):
<validation:config name="Validation_Configuration" doc:name="Validation Configuration">
<validation:exception-factory class="com.mycomp.validation.MyExceptionFactory"/>
</validation:config>
In your flow configure acustom-validator and reference your configuration with exception factory, your validator implementation and the type of exception you want to throw with exceptionClass. To be able to throw any kind of Exception, specify java.lang.Exception or a class from which the custom exceptions you'll want to use can inherit:
<flow name="validation-exceptionFlow">
...
<validation:custom-validator
config-ref="Validation_Configuration"
class="com.mycomp.validation.MyValidator"
exceptionClass="java.lang.Exception"
doc:name="Validation" />
...
</flow>
Depending on your need you may want to specify exceptionClass differently, the idea being that your actual exceptions should extend it.
Yout ExceptionFactory implementation is then up to you. You can return whatever exception you want... For example:
public class MyExceptionFactory implements ExceptionFactory{
#Override
public <T extends Exception> T createException(ValidationResult result, Class<T> exceptionClass, MuleEvent event) {
return (T) createException(result, exceptionClass.getCanonicalName(), event);
}
#Override
public Exception createException(ValidationResult result, String exceptionClassName, MuleEvent event) {
//...
//some logic to identify which kind of exception you want to throw
//from result and event
//...
if(something) {
return new SomeException("Something happened");
} else if (somethingElse) {
return new AnotherException("I am en error...");
} else {
return new BananaException("Ook");
}
}
}
It appears the interface has two methods, one returning a generic and the other a plain Exception. Not knowing the specific usage of your ExceptionFactory I won't be able to provide much guidance, but be aware that Mule may call any of these methods, and the doc provides some requirements:
The above interface receives the Event that was rejected by the
validation and the validator that raised the error. This method is
intended to return the exception to be thrown but not to throw it.
Implementations of this interface should never throw exceptions. They
should also be thread-safe and have a public default constructor. See
Also
I'd like some feedback on a situation where:
A method constructs an object, but some of the work done while constructing it might fail. This will lead to an object that is missing some data. I want to give the user of this method the ability to handle the object if complete but also handle the object if incomplete while also being able to handle the exception thrown.
Use Case:
I'm reading a file from disk into a POJO and some of the file attributes like date created can throw an exception while being read from the Operating System. In that case I'm throwing a custom exception but I also want the user to be able to handle that incomplete file representation (POJO).
My solution:
I used a custom exception that wraps the thrown exception and the incomplete object.
My code:
public FileDto getFromFile(File f) throws IncompleteFileDtoException {
FileDto dto = new FileDto();
dto.setName(f.getName());
dto.setPath(f.getAbsolutePath());
dto.setDirectory(f.isDirectory());
dto.setSize(f.length());
dto.setModifiedAt(f.lastModified());
try {
BasicFileAttributes attr = Files.readAttributes(f.toPath(), BasicFileAttributes.class);
dto.setCreatedAt(attr.creationTime().toMillis());
}
catch(Exception e)
{
throw new IncompleteFileDtoException("Unable to transform " +f.getAbsolutePath() + " to DTO.", e, dto );
}
return dto;
}
public static class IncompleteFileDtoException extends Exception
{
private FileDto fileDto;
public IncompleteFileDtoException(String message, Exception e, FileDto fileDto)
{
super(message,e);
this.fileDto = fileDto;
}
public FileDto getFileDto() {
return fileDto;
}
}
What negative effects could this code have ?
Your example only contained one value that might lead to a problem but as soon as you have multiple values you end up with quiet complicated code, because you have to keep the information if such an exception should be thrown.
Personally a better approach might be to just set fitting default values (if not just a null) if the processing failed but it's OK for the initialization of that particular value. And if it's OK that a value can be null you can just the whole exception-throwing. If you need to know if there was a problem during setup, add a flag in that object that gives the information if something failed that can be cheecked. That would also allow you to pass the object around without losing that information in subsequent classes, etc.
In short: Exception should only indicate exceptional situations, i.e. that an object can't be used and not to indicate expected situations
I offer you to use Builder pattern. Do create FileDtoBuilder and put it into exception. When you read file successfully, the do create FileDto instance from existed FileDtoBuilder.
Gang Of Four Design Patterns
https://en.wikipedia.org/wiki/Builder_pattern
I would like to customize java exceptions class by adding an attribute to them. It could be as simple as the following attribute:
boolean isThisStupid;
void setIsThisStupid(boolean iValue);
boolean getIsThisStupid();
Every time I would instantiate an exception, like a NullPointerException, or an IllegalArgumentException, it would contains this attribute.
Since I do not have the source code of Java, I cannot of course edit the Exception base class.
I've considered using the decorator pattern, using an "ExceptionDecorator" class implementing an IException interface, however, doing this I would lose the initial exception type, which I do not want. For example for:
IException mException = new ExceptionDecorator( new NullPointerException() );
I would get:
mException instanceof ExceptionDecorator; //true
mException instanceof NullPointerException; //false
I want my custom exception to be an instance of NullPointerException.
This is totally generic, I want this to be working with any subclass of Exception.
Is this even possible ? If yes, maybe there's a pattern which could help me and I don't know about ?
I've done my best to be clear, if I'm not, please ask for more details and I will rephrase the initial topic.
Thanks
I want my custom exception to be an instance of NullPointerException.
It is not possible at compile time. To do what you want, you should create dynamically your exception class at runtime with Javasist for example.
Otherwise for static typing, you could use decorators. Decorators have to use the same interface/class than decorated objects. It is the base of the decorator.
In your case, the base class cannot be a new interface you create since you cannot change the code of existing exceptions. So the common abstract class between decorator and decorated objects is Exception.
You could have a decorator like that :
public class DecoratorException extends Exception{
private Exception decorated;
private boolean isStupid;
public DecoratorException(Exception exception){
this.decorated = exception;
}
public void setStupid(boolean iValue){
// TODO
}
public boolean getStupid{}{
// TODO
}
// get effective exception
public Exception getEffectiveException(){
return decorated;
}
// decorate the method you wish
// for example toString()
public String toString(){
return decorated.toString() + ", isStupid=" + isStupid);
}
}
The idea of Decorator is adding behavior to the decorated object.
In my example, I decorated the toString() method to display the new field with its value.
You can then rise an exception like that :
Exception e = new DecoratorException(new IllegalArgumentException());
e.setStupid(true);
throw e;
Thanks you all for your answers, it seems like nothing can really satisfy what I need. So I may just change my idea rather than forcing something that would turn awkward and not maintainable
I think your best bet here would be to continue with the decorator pattern here as you described, and instead of using instance of, create another method in your exception class (#containsInstanceOf or something) and using that in your code to check the contained type.
I think the only way to add the behavior you want would be to mess with the byte code like Lombok does, or by creating proxy objects. Both of those are pretty messy and it's probably easier to just use the decorator pattern and deal with the fact that instance of won't work.
For getting the exception class to extend NullPointer, do something like this:
public MyNewException extends NullPointerException
{
/*define methods and variables*/
}
For a class to work with any subclass of exception, you would have to define it as follows:
public MyNewException extends Exception
{
/*define stuff*/
}
Let me know if this is not what you want to be done.
I have some function works with database.
I have set a try/catch for error handling here, and display a message, It works fine.
Now the class calling this delete function need to know if there is a error or not. In my case : refresh the GUI if success, nothing to do if fail (as there already show up a message message dialog).
I come up a idea to return boolean in this function.
public static Boolean delete(int id){
String id2 = Integer.toString(id);
try {
String sql =
"DELETE FROM toDoItem " +
"WHERE id = ?;";
String[] values = {id2};
SQLiteConnection.start();
SQLiteConnection.updateWithPara(sql, values);
} catch (SQLException e) {
Main.getGui().alert("Fail when doing delete in DataBase.");
System.out.println("Exception : "+ e.getMessage());
return false;
}
return true;
}
Don't know if this is good or bad, please tell.
EDIT :
Here is more detail for How do I use :
Let's say the code above is inside Class A,
in Class B :
public boolean deleteItem(int id){
int i = index.get(id);
if(theList[i].delete()){ //<---- here is the function from Class A
theList[i] = null;
index.remove(id);
retutn true;
}
retutn false;
}
I need to pass the boolean in more than one class, I don't know if that can better through...
in Class C :
public void toDoList_deleteItem(){
MyButton btn = (MyButton)source;
int id = btn.getRefId();
List toDoList = Main.getToDoList();
if(toDoList.deleteItem(id)){ //<-------function in Class B
Main.getGui().refresh();
}
}
Edit 2 :
I have notice the question is somehow more likely asking "What should I handle a Exception at database Layer that affect to GUI Layer ?"... Something like that. Please correct me if the question title should be edit.
It looks like you are returning a boolean status to indicate that an exceptional condition had occurred. Generally, this is not a good practice, for two reasons:
It encourages an error-prone way of handling exceptions - it is very easy to miss a status check, leading to ignored errors
It limits your API's ability to report errors - a single pass/fail bit is not always sufficient, it may be desirable to pass more information about the error.
A better approach would be to define an application-specific exception, and use it in your API. This forces the users of your API to pay attention to exceptional situations that may happen, while letting you pass as much (or as little) additional information as you find necessary. At the same time, your code does not get polluted with if (!delete(id)) { /* handle error */ } code on each API call, shrinking your code base, and improving its readability.
Can you tell me more about "define an application-specific exception", or show some code example please?
Here is how I would do it:
public class DataAccessException extends Exception {
... // Define getters/setters for passing more info about the problem
}
...
public static void delete(int id) throws DataAccessException {
try {
... // Do something that may lead to SQLException
} catch (SQLException se) {
// Do additional logging etc., then
throw new DataAccessException("Error deleting "+id, se);
}
}
Note: It is common to give custom exceptions four constructors mirroring the constructors of the Exception class to allow exception chaining. The constructors are described here.
As long as you do not want the caller to know what happens, just that it fails (and that failing is part of its intended behavior) you should be fine.
That being said, I am noticing this: Main.getGui().alert("Fail when doing delete in DataBase.");.
It would seem that you are accessing the GUI layer from some other place. This might cause issues should you decide to multi-thread your application. Also, it is usually considered good practice to have your layers not intersect.
Don't return a Boolean, return a boolean. Since this is not an exception / error condition, it is fine.
Exceptions should be used when you don't expect a failure.
In your case, if it's fine for you that a SQLException is thrown and does not affect your program, it's ok to return a boolean.
If the SQLExcetion causing the delete to fail can cause problems in another part of your application it's better to throw an exception.
Edit:
Based on your edits, it seems that you are doing some maintenance and cleaning when an error happens. In such a case I would recommend to use Exceptions better than using booleans to control the execution.
This question is primarly opinion based. Personally I would prefer not to catch the exception at that point.
Depending on what the caller of delete() should do, you might need other resulutions. So you should better add a throw statement and let the calling method decide if the error is critical - or if it can proceed.
Just true and false is not necessary enough to let the caller decide correctly. He won't know if deletion fails due to database errors, due to foreignkey constraints, or something else.
letting the exception bubble up the call stack will provide the caller with the exact error going on, increasing the chance to handle the error in a proper way, or just displaying a custom error message helping the user to take proper actions.
I'm using the java.util.concurrency framework for the first time. Here's a very simplified version of what I'm doing. For those not intimately familiar with the framework, future.get() executes a Callable object defined in the future. future.getOriginatingRequest() returns an object I set in the future for use by the Callable object and I'm just trying to log which originating request object failed (its enough to know the class name of it).
try {
future.get();
} catch (ExecutionException e) {
logger.error("Failed to execute future with id '" +
future.getOriginatingRequest().getClass().getName() + "'");
}
The problem I'm having is that the logging framework is outputting this:
Failed to execute future with id '$Proxy22'
Thus instead of the real class name I am getting $Proxy22 or some other number. Is there a way to get ahold of the real class name rather than the proxy name? Bonus points is someone can clearly explain why I'm getting the proxy string in the first place!
I can answer the bonus question: the string is the name of a dynamic Proxy class, generated in runtime.
As for how you can get to the masked class, there's not even a guarantee that one exists at all. The only thing you can do is to call Proxy.getInvocationHandler() on your proxy object and hope that the invocation handler will reveal more information (unlikely but may be worth a shot).
I find good for me solution on http://www.techper.net/2009/06/05/how-to-acess-target-object-behind-a-spring-proxy/
#SuppressWarnings({"unchecked"})
protected <T> T getTargetObject(Object proxy, Class<T> targetClass) throws Exception {
if (AopUtils.isJdkDynamicProxy(proxy)) {
return (T) ((Advised)proxy).getTargetSource().getTarget();
} else {
return (T) proxy; // expected to be cglib proxy then, which is simply a specialized class
}
}
Usage
#Override
protected void onSetUp() throws Exception {
getTargetObject(fooBean, FooBeanImpl.class).setBarRepository(new MyStubBarRepository());
}
i'm guessing that the proxy class is a subclass of the class you're looking for. especially if the class you're looking for is a class you wrote.
can you access the inheritance tree for the object you found? maybe through reflection?