Add an attribute to any java exception - java

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.

Related

Obtaining the original Java class while using instanceof and casting

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.

How do you name a class/method that only calls other methods?

Say I follow the Single Responsibility Principle and I have the following classes.
public class Extractor {
public Container extract(List<Container> list) {
... some extraction
}
}
public class Converter {
public String convert(Container container) {
... some conversion
}
}
As you can see it's following the principle and all the names of the classes/methods tell what they do. Now I have another class that has a method like this.
public class SomeClass {
private Extractor extractor = new Extractor();
private Converter converter = new Converter();
private Queue queue = new Queue();
public void someMethod(List<Container> list) {
Container tmp = extractor.extract(list);
String result = converter.convert(tmp);
queue.add(result);
}
}
As you can see the "someMethod"-Method does call extract, convert and add. My question is now, how do you call such a class/method? It's not actually extracting, converting or adding but it's calling those?
If you name the method after its responsibility what would that be?
Well since you seem to add to a queue and you don't return anything I'd call it addToQueue. The fact that you convert + extract is implementation detail that I don't think needs to be exposed.
What about processAndQueueMessage?
Also (not related), you shouldn't create (using new) the Extractor and Converter in your SomeClass, you should rather inject them (at construction or in setters), and use interfaces to them. That will make it easier to test, and reduce coupling between implementations.
// Assuming Converter and Extractor are interfaces to the actual implementations
public class SomeClass {
private final Extractor extractor ;
private final Converter converter;
private Queue queue = new Queue();
public SomeClass(Extractor extractor, Converter converter) {
this.converter = converter;
this.extractor = extractor;
}
public void someMethod(List<Container> list) {
Container tmp = extractor.extract(list);
String result = converter.convert(tmp);
queue.add(result);
}
}
And you create it using:
final SomeClass myProcessor = new SomeClass(new MyExtractorImplementation(), new MyConverterImplementation());
(Or use a DI container, like Spring or Pico)
What you do is think about the composite meaning of the sequence of method calls, turn that into a concise verb or verb phrase and use that as the name. If you can't come up with a concise name then you could use a generic / neutral name (like "process") or use something completely bogus (like "sploddify").
If you want the name to be really generic, I'd go with addToQueue() or populateQueue() since getting something into that object seems to be the point of the method.
But really at that level I'd call it by what business logic it's trying to accomplish, in which case the name really depends on what it's being used for.
If you can't come up with a good name, it is an indication that your procedural abstraction is rather arbitrary / artificial, and a possible hint that there might be a better way to do it. Or maybe not.
Sounds like some kind of builder class. You get data in one format, convert it and then create some kind of output format. So how about "SomethingSomethingBuilder"?
I'm assuming someone downvoted me because I forgot to provide a good name for the method. Sorry about that.
So this method adds incrementally data into your builder class. I would call it, "Add", "AddData" or "Push" (I'd probably go with push because that has very similar meaning in many standard classes).
Alternative to "Builder" could potentially be "SomeKindOfCreator". Obviously you would name it based on whatever it is your class is actually creating.

How to get arguments passed to method that called this method?

In Java, it is possible to get the class and method that called the current method (the method in which you get the StackTrace).
Can I get the arguments that were passed to the method that called this method?
I need this for debugging purposes.
Eg:
baseClass {
initialFunc(input) {
var modifiedInput = input + " I modified you";
otherClass.doSomething(modifiedInput);
}
}
otherClass {
doSomething(input) {
//GET THE ARGUMENTS PASSED TO THE METHOD OF THE CLASS THAT CALLED THIS METHOD
}
}
Can one get this information from the stacktrace, or are there other means?
(Note that I need to be able to do this in runtime and cannot actually change the source of baseClass, this is going to be a feature of my debugging class that does not know the source beforehand)
I don't believe this is possible using the standard Java API.
What you could do is to use AspectJ, place a point-cut at the calling method, save the arguments, place a point-cut at the called method and pass on the arguments.
Another option (slightly more advanced) is to use a custom, bytecode-rewriting, class loader that saves the original arguments, and passes them on as extra arguments to the next method. This would probably take a day or two to implement. Suitable frameworks are BCEL or ASM.
I think this could be possible, because input is out of scope but isn't yet accessible for garbage collection, so the value still exists, but unfortunately I don't believe there is an default API way to access it. This could be maybe possible with a custom implemented NDC (nested diagnostic context) for the logging approach.
I'm not sure why you'd ever want to do this in Java?
The only way I can think of is to create a custom wrapper object for the passed string, thus sending the reference to the wrapper instead of a new string each time.
I'd advice against it, though, since it clutters your original code, and makes it even more error prone.
Might this problem not be solved using a debugger, like the one built into eclipse, to inspect your state?
In my case, I needed to get a parameter value has been passed to a method in a certain stack frame to be used later within the execution flow
I used ThreadLocal to store it and when I needed it I was able to retrieve it at any point in code as I declared it as public static
here is a skeleton example
public static final ThreadLocal<SomeType> IMPORTANT_THREAD_LOCAL_FOR_BLA = ThreadLocal.withInitial(whatever);
methodWithImportantParam(SomeType importantValue){
// save it in the static threadLocal Field
this.IMPORTANT_THREAD_LOCAL_FOR_BLA.get()=importantValue;// code to set the value
// continue method logic
}
and somewhere in code where you need that value
YourClass.IMPORTANT_THREAD_LOCAL_FOR_BLA.get()
but make sure the execution flow that you set the value then you retrieve it
hope my answer add something valuable to this question
You can get name of caller method and its class, but you have to add some code in current method:
public static void main(String[] args) throws Exception {
call();
}
private static void call() {
Exception exception = new Exception();
for(StackTraceElement trace : exception.getStackTrace()){
System.out.println(trace.getMethodName());
}
}
This will print "call" and "main", methods name in called order (reverse).
This is possible using Reflection API !
public class StackTrace {
public static void main(String args[]) {
StackTrace st = new StackTrace();
st.func();
}
public void func() {
OtherClass os =new OtherClass();
os.getStackTrace(this);
}
}
class OtherClass {
void getStackTrace(Object obj) {
System.out.println(obj.getClass());
}
}

Loading a Class from a String

I want to instantiate a class by the value of a String. I found several tutorials that show several methods for doing this. The class MUST inherit from a certain interface, ImplementMe which has a special method called runMe(). So here's what I tried:
ImplmentMe a =
(ImplementMe) ImplementMe.class
.getClassLoader()
.loadClass("my.package.IImplementedYou")
.newInstance();
a.runMe();
It works, but it's so ugly. I at least expected not needing a cast. Please tell me there is a better way.
No, there is no better way (by design). You are not supposed to do this, Java is designed as a type-safe language. However, I can understand that you sometimes need to do things like this, and for that purposes you can create a library function like this:
public <T> T instantiate(final String className, final Class<T> type){
try{
return type.cast(Class.forName(className).newInstance());
} catch(InstantiationException
| IllegalAccessException
| ClassNotFoundException e){
throw new IllegalStateException(e);
}
}
Now your client code can at least call this method without casting:
MyInterface thingy =
instantiate("com.foo.bar.MyInterfaceImpl", MyInterface.class);
Try Class.forName("my.package.IImplementedYou").
Here's how I would do it:
ImplementMe noCastNeeded =
this.getClassLoader()
.loadClass("my.package.IImplementedYou")
.asSubclass(ImplementMe.class).newInstance();
There are some Exceptions to catch but that's ok I think. :)
In all essence that is what will happen regardless of whether you're using a third party toolkit for it or not. Casting the object will inherently be mandatory unless expecting an Object. You can however make a routine which does that for you:
public <T> T instantiateObject(String name, Class<T> cls) throws Exception {
return (T) Class.forName(name).newInstance();
}
Which you can use:
AClass cls = instantiateObject("com.class.AClass", AClass.class);
But if you come this far, the String name is actually redundant (given AClass is a concrete class). You might as well:
public <T> T instantiateObject(Class<T> cls) throws Exception {
return (T) Class.forName(cls.getCanonicalName()).newInstance();
}
Which you can use:
AClass cls = instantiateObject(AClass.class);
You can shorten it a bit like
ImplementMe a = (ImplementMe) Class
.forName("my.package.IImplementedYou")
.newInstance();
but you can't get rid of the cast. There may be a way to avoid the cast, but only if you can avoid the subproblem of loading class by name.
The alternative is to use forName, but it does not get much better than what you currently have:
ImplementMe a =
(ImplementMe) Class.forName("my.package.IImplementedYou").newInstance();
a.runMe();
Indeed, forName will use getClassLoader().loadClass() behind the scenes to load the class, as you can see in the source code of Class.java.
You will need a cast, because the compiler cannot tell from the code that the object is of type ImplementMe. It thus requires the programmer to issue a cast, which will throw a ClassCastException if the object is not an ImplementMe instance.
What you have may work, but you don't have to load the class using the same classloader that loaded ImplementMe. This should work equally well:
Object newInstance = this.getClass().getClassLoader().loadClass("my.package.IImplementedYou").newInstance();
The important thing is that the classloader knows both the class file with the implementation of "my.package.IImplementedYou" and the class with the implementation of "ImplementMe".
You may explicitly check that IImplementedYou really implements ImplementMe like this:
if(newInstance instanceof my.package.IImplementedYou) {
((ImplementMe)newInstance).runMe();
}
You may also check that IImlementedYou really is implementing the interface before creating the instance:
Class c = this.getClass().getClassLoader().loadClass("my.package.IImplementedYou");
if(ImplementMe.class.isAssignableFrom(c)) {
Object newInstance = c.newInstance();
}
(MyInterface)Class.forName(className).newInstance()

Throwing an Exception Not Defined in the Interface

What is the best practice to follow when you need to throw an exception which was not defined in an interface that you are implementing?
Here is an example:
public interface Reader
{
public abstract void read() throws IOException;
}
public class CarrotReader implements Reader
{
public void read() throws IOException {}
}
public class CupcakeReader implements Reader
{
public void read() throws IOException, CupcakeException {}
}
In this case, you have a specific exception that occurs when reading cupcakes, so you want to throw an exception related to this. However, Reader doesn't define this type of exception in its interface, so what do you do? Furthermore, it doesn't make sense to add CupcakeException to the throws clause in the Reader interface, because this type of exception is specific to CupcakeReader. One way around this is to have Reader define read such that it throws some parent type, like Exception, but then you lose the context for the exception. What should you do in this situation? Thanks!
Another interesting situation that has been brought up involves an interface over which you have no control. In this case, what is the best way to indicate that a problem has occurred?
For illustrative purposes, here is another example:
public interface Reader
{
public abstract void read();
}
public class CupcakeReader implements Reader
{
public void read() throws CupcakeException {}
}
In this case, you cannot change Reader, but you want to indicate that a problem has occurred in CupcakeReader's read method.
You may have to create an exception of the expected type instead.
... catch(CupcakeException e) {
throw new IOException("The sky is falling", e);
}
Use something called ReaderException that will serve as the root interface of your exception hierarchy. ReaderException will also provides a link to other exceptions that get thrown due to lower level exceptions.
Exception is part of the interface. Define a generic parent for all your exceptions in the interface if you can redefine the interface.
You can also make CupcakeException a child of IOException.
Just don't use checked exceptions.
The example you showed is one of the reasons checked exceptions are bad.
The main reason though is that the user of your cupcake reader will have to handle your exception regardless of whether he is interested in it or not.
So instead of:
Value value = reader.read();
You are forcing him to do this:
Value value = null;
try {
value = reader.read();
} catch (Exception e) {
// now what??
}
value.doSomething(); // potential NPE here
Think which one is better, more readable and less error prone and just stop using checked exceptions.
EDIT:
I am surprised with the negative rating. Are there people who still think that checked exceptions are great? If so here are some references why you shouldn't use checked exceptions:
No modern framework uses checked exceptions (Spring, EJB3 etc)
Article with code examples here
StackOverflow topic
Effective Java (sections 58 and 59) - here
Perhaps you could make an abstract ReaderSpecificException class, put it in the Interface, and
subclass CupcakeException from this abstract class.
If you create a higher abstract exception that works as a base class for CupCakeException you don't bind the Reader Interface to a specific implementation like you would be doing if you added the CupCakeException to the Reader interface.
If you don't let one Exception inherit from another there is a constructor in the exception class that takes a throwable as second argument like Thorbjørn Ravn Andersen allready showed in his short code example. The enables you to generate a more abstract exception and every part of your code that needs to know more then just "there is an error" can look for the cause of the higher exception.

Categories