Java Reflection Exception Jungle

A

alan

A major annoyance for me is that the reflection errors do not
have a common root. What was the logic behind that?
 
V

Vincent Cantin

A major annoyance for me is that the reflection errors do not
have a common root. What was the logic behind that?

Can you say about what errors you are talking about ?
Aren't they all extending the class Error ?

Vincent
 
A

alan

Can you say about what errors you are talking about ?
Aren't they all extending the class Error ?


They're all extending Exception, most RuntimeException.

The problem is that Method.invoke throws:

- Object
+- Throwable
+- Exception
+- IllegalAccessException
+- InvocationTargetException
+- RuntimeException
+- IllegalArgumentException

Which means that function signatures look like this.

void doSomeReflection() throws IllegalAccessExcpetion,
InvocationTargetException, IllegalAccessExcpetion,
NoSuchMethodException, SecurityException;

Or else like this.

void doSomeReflection() throws Exception;

That that last one is a no-no.

What was the logic behind that?
 
C

Chris Uppal

Which means that function signatures look like this.

void doSomeReflection() throws IllegalAccessExcpetion,
InvocationTargetException, IllegalAccessExcpetion,
NoSuchMethodException, SecurityException;

Just:
public Object invoke(Object obj, Object[] args)
throws
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
will cover it. Indeed the above is cut-n-pasted from the JavaDoc.
Three separate "kinds" of exception is, um, exceptional, but it's not clear
that they /should/ share any natural superclass.

OTOH, since the method invoked by reflection may throw /anything/ I don't see
much point (except the documentary value) in declaring Method.invoke() to throw
anything more specific than Throwable.

-- chris
 
M

Mike Schilling

I think the OP intends doSomeReflection() to find the method as well as
invoke it, though in that case I'd probably catch NoSuchMethodException and
SecurityException within doSomeReflection and rethrow some exception that
means "no accessible method found".
Just:
public Object invoke(Object obj, Object[] args)
throws
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
will cover it. Indeed the above is cut-n-pasted from the JavaDoc.
Three separate "kinds" of exception is, um, exceptional, but it's not
clear
that they /should/ share any natural superclass.

OTOH, since the method invoked by reflection may throw /anything/ I don't
see
much point (except the documentary value) in declaring Method.invoke() to
throw
anything more specific than Throwable.

Anything the invoked method throws is wrapped by InvocationTargetException.
The defined exceptions do IMHO a reasonable job of separating out the things
that can go wrong:

IllegalAccessException
you're not allowed to call this method

IllegalArgumentException
you can call this method, but not with the supplied arguments

InvocationTargetException
you called the method just fine, but it threw an exception
 
J

John C. Bollinger

They're all extending Exception, most RuntimeException.

The problem is that Method.invoke throws:

- Object
+- Throwable
+- Exception
+- IllegalAccessException
+- InvocationTargetException
+- RuntimeException
+- IllegalArgumentException

Which means that function signatures look like this.

void doSomeReflection() throws IllegalAccessExcpetion,
InvocationTargetException, IllegalAccessExcpetion,
NoSuchMethodException, SecurityException;

Or else like this.

void doSomeReflection() throws Exception;

That that last one is a no-no.

Or like this:

void doSomeReflection() throws OopsInMyReflectionException;

In other words, if you want to present a simpler API then you can catch
all the various exceptions internally and wrap each in an instance of
some for-purpose custom exception.
What was the logic behind that?

To make you think twice before using reflection?

IMO, reflective method invocation is almost always a sign of poor
application design. Except in a few very specialized cases, if you have
enough information about an object to sensibly invoke methods on it via
reflection, then you have enough information to construct a means to
invoke them normally. This may involve defining an interface that the
object's class must implement, and assigning the object reference to a
variable of the interface type. There are sometimes other alternatives.


John Bollinger
(e-mail address removed)
 
A

alan

Which means that function signatures look like this.

void doSomeReflection() throws IllegalAccessExcpetion,
InvocationTargetException, IllegalAccessExcpetion,
NoSuchMethodException, SecurityException;

Just:
public Object invoke(Object obj, Object[] args)
throws
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
will cover it. Indeed the above is cut-n-pasted from the JavaDoc.
Three separate "kinds" of exception is, um, exceptional, but it's not clear
that they /should/ share any natural superclass.

It covered Method.invoke, but not the calls to Class.getMethod
which go hand in hand. Yes. The three cover invoke. However, if
you have reflection as part of your package/library, and you are
not going to handle reflection exceptions yourself, your
signatures start to look like the above.

Agreed?
OTOH, since the method invoked by reflection may throw /anything/ I don't
see much point (except the documentary value) in declaring Method.invoke()
to throw anything more specific than Throwable.

I disagree there. There is a difference in an error in the reflection and
an error in the reflected class. Different types of exception.
 
A

alan

I think the OP intends doSomeReflection() to find the method as well as
invoke it, though in that case I'd probably catch NoSuchMethodException and
SecurityException within doSomeReflection and rethrow some exception that
means "no accessible method found".

Yes. That is the intention of the OP. And I'm asking about for best
practices, since it looks like a general issues with Java exceptions.
Just:
public Object invoke(Object obj, Object[] args)
throws
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
will cover it. Indeed the above is cut-n-pasted from the JavaDoc.
Three separate "kinds" of exception is, um, exceptional, but it's not
clear
that they /should/ share any natural superclass.

OTOH, since the method invoked by reflection may throw /anything/ I don't
see
much point (except the documentary value) in declaring Method.invoke() to
throw
anything more specific than Throwable.

Anything the invoked method throws is wrapped by InvocationTargetException.
The defined exceptions do IMHO a reasonable job of separating out the things
that can go wrong:

IllegalAccessException
you're not allowed to call this method

IllegalArgumentException
you can call this method, but not with the supplied arguments

InvocationTargetException
you called the method just fine, but it threw an exception

Agreed. This part I like. However, it is common case where I
want to lump handling for all reflection exceptions into one
category, or two, errors in the reflection specfication (no such
method, security, arguments, et al.) and errors in the target
invocation. I'd prefer a heirarchy like so:

- ReflectionException
- IllegalAccessException
- IllegalArgumentException
- InvocationTargetException

My catch ladder can be:

try {
foo.doSomeRefelction();
} catch (InvocationTargetException e) {
System.err.println("Errors from the other side.);
e.printStackTrace();
} catch (ReflectionException e) {
System.err.println("Faulty incantation.");
e.printStackTrace();
} catch (FooException e) {
System.err.println("Errors from this side.");
e.printStackTrace();
}

I'm asking about this because I'm doing a lot of reflection, and
I've created some adaptor classes to tame this problem, and I'm
starting to take them seriously.

Observer patterns have the same problem of not know the types of
execptions that are going to get raised. I do a lot of SAX which
faces a similar problem, everything is a SAXException, even when
its not a SAXException.
 
A

alan

Or like this:
void doSomeReflection() throws OopsInMyReflectionException;
In other words, if you want to present a simpler API then you can
catch all the various exceptions internally and wrap each in an
instance of some for-purpose custom exception.

Righto. Was concerned about getting into the perpetually wrapped
exception with that. (Not being contrarian. Stating my concern.)
To make you think twice before using reflection?

Um, okay, a valid design reason is to say, we think you should
design your own exception heirarchy, we can't anticiplate your
needs, but we've atomized it for you. If you use it once or
twice in your program, here's what you need to worry about. If
you're writing a reflective application, then think of an
exception handling strategy approprite for your application.

That to me is a more professional sentiment than discouraging
use. I'd hate to think the API was nagging me, punishing me for
my design decisions.

I suppose then, I should proceed to develop a reflection API as
I like it.

Are there any other design reasons?
IMO, reflective method invocation is almost always a sign of poor
application design. Except in a few very specialized cases, if you have
enough information about an object to sensibly invoke methods on it via
reflection, then you have enough information to construct a means to
invoke them normally. This may involve defining an interface that the
object's class must implement, and assigning the object reference to a
variable of the interface type. There are sometimes other alternatives.

IMO, reflective method invocation is useful for cofiguration and
for testing. Two places where speed is not an issue, but
flexibilty is. Two very common appliations.

JUnit, Ant, XStream, JavaBeans, BeanShell, OGNL, Jetty, etc.
Plenty of quality projects use reflection appropriately.

There are many ways to abuse reflection. I know.
 
J

John C. Bollinger

(e-mail address removed) wrote:

[Alan:]
[Me:]
Or like this:

void doSomeReflection() throws OopsInMyReflectionException;

In other words, if you want to present a simpler API then you can
catch all the various exceptions internally and wrap each in an
instance of some for-purpose custom exception.
[Alan:]
Righto. Was concerned about getting into the perpetually wrapped
exception with that. (Not being contrarian. Stating my concern.)

If you don't want to wrap then discard the original exception instead.
I don't see how it's useful to gratuitously dump potentially valuable
data, but you can do it if it better suits your sensibilities.
Um, okay, a valid design reason is to say, we think you should
design your own exception heirarchy, we can't anticiplate your
needs, but we've atomized it for you. If you use it once or
twice in your program, here's what you need to worry about. If
you're writing a reflective application, then think of an
exception handling strategy approprite for your application.

I was being a bit flippant, sorry. Reflection seems to hold an
unhealthy fascination for some people, so I and some others here tend to
discourage its use. Wherever you can avoid or minimize your use of
reflection you are better off. As for the exceptions thrown by
Method.invoke(), there are two general cases:

(1) Your reflective invocation was erroneous with respect to Java and/or
the reflection machinery. This may result in an IllegalAccessException,
IllegalArgumentException, or NullPointerException, depending on the
nature of the problem. The latter two are unchecked exceptions, and
thus do not need to be declared. They involve situations where your
program is just plain buggy (attempting to supply the wrong number or
types of parameters, or invoking an instance method without an
instance). The former involves a situation that is a compile-time error
in non-reflective code (the method is not accessible to the invoking
class). If you don't pay attention to the possibility then this
reflection can arise during "normal" reflective exploration and use of a
class.

(2) Your reflective invocation produced an application failure. This
generally results in an InvocationTargetException (the method terminated
abnormally by throwing an exception), but if an
ExceptionInInitializerError is generated during the method invocation
then it is propagated outward. You don't need to declare the Error, of
course.

By breaking down the situation this way, the Reflection API gives you
the opportunity to handle each distinct situation in a manner
appropriate for your application. You only need explicit handling for
the two checked exceptions: IllegalAccessException and
InvocationTargetException. You would need at least the latter, or
something like it, in any generic reflection-type API.
That to me is a more professional sentiment than discouraging
use. I'd hate to think the API was nagging me, punishing me for
my design decisions.

The Reflection API is less than straightforward to use because
Reflection is less than straightforward. You have to worry about a
great many things that the compiler or JVM handles for you with normal
method invocations. (Try coding a correct, fully general algorithm for
choosing the right overloaded method to invoke for a given set of
arguments, for instance.) The API is not nagging you: it is simply
exhibiting its own nature.
I suppose then, I should proceed to develop a reflection API as
I like it.

What's wrong with the API you already have?
IMO, reflective method invocation is useful for cofiguration and
for testing. Two places where speed is not an issue, but
flexibilty is. Two very common appliations.

JUnit, Ant, XStream, JavaBeans, BeanShell, OGNL, Jetty, etc.
Plenty of quality projects use reflection appropriately.

Testing, yes. JUnit is one of the examples I was thinking of. Do note,
however, that even in JUnit reflection is only used behind the scenes to
provide convenience features to the test writer -- it is not exposed in
the API, and it is possible to write full JUnit test suites that do not
rely on the reflection-enabled convenience features.

The other category that occurred to me is application frameworks that
are expected to deal with objects defined by non- or only partially
programmatic specifications. J2EE containers and JavaBean frameworks
fall into this category. Again, reflection is an enabling technology
for such meta-applications, not one exposed as part of an API. It is
rarely necessary to design a regular application this way.

Both of those are commonly _used_ types of applications, but they are
not commonly _written_ types of applications. I stand on my position
(clarified) that it is rare to need to use reflective method invocation
in an application, that doing so is vastly inferior to using normal
method invocation when that is possible, and that therefore reflective
method invocation is almost always a sign of poor application design or
implementation.

Do note that it is possible to reflectively instantiate classes but
invoke methods on them normally. This is what a well-designed plug-in
type API will do; I believe Ant's custom tasks are an example, and JDBC
drivers certainly are. This is the sort of use that I generally think
of in support of custom application configuration, and is not covered by
my arguments against reflective method invocation.


John Bollinger
(e-mail address removed)
 
C

Chris Uppal

It covered Method.invoke, but not the calls to Class.getMethod
which go hand in hand. Yes. The three cover invoke. However, if
you have reflection as part of your package/library, and you are
not going to handle reflection exceptions yourself, your
signatures start to look like the above.

Agreed?

Yes.

But I'm not convinced of the value in allowing the exceptions to escape "raw".

The point of wrapping the java.lang.reflect.* stuff up in your own library is
presumably to make it less inconvenient to use, so /forcing/ client code to
distinguish between the various reasons a reflective invocation can fail seems
counterproductive to me. I'd wrap the raw exception (non-)hierarchy up in my
own little hierarchy (and I'd probably extend the API of the exceptions I used
to include (IMO) proper OO methods like isProgrammingError() (some potential
exceptions are, some aren't, and I don't think that client code should be
forced to switch-on-class to tell which is which).

-- chris
 
A

alan

Yes.

But I'm not convinced of the value in allowing the exceptions to escape "raw".

The point of wrapping the java.lang.reflect.* stuff up in your own
library is presumably to make it less inconvenient to use, so
/forcing/ client code to distinguish between the various reasons a
reflective invocation can fail seems counterproductive to me. I'd
wrap the raw exception (non-)hierarchy up in my own little
hierarchy (and I'd probably extend the API of the exceptions I
used to include (IMO) proper OO methods like isProgrammingError()
(some potential exceptions are, some aren't, and I don't think
that client code should be forced to switch-on-class to tell which
is which).

That last part is another thing that has been a cause for
consideration for me lately. What good is exception handling if
you do not provide the information necessary to fix the
exception? Why FileNotFoundException cannot have a getFile() method?

In any case, in another posts on this thread I've talked about
the same thing. Heirarchy, but with a common ReflectionException root.

Your signatures can look like:

public void doSomeReflection() throws ReflectionException;

In other, similiar problems, I'm moving away from checked
exceptions, but they seem to make sense here, still.
 
A

alan

(e-mail address removed) wrote:

[Alan:]
Which means that function signatures look like this.
[Me:]
Or like this:

void doSomeReflection() throws OopsInMyReflectionException;

In other words, if you want to present a simpler API then you can
catch all the various exceptions internally and wrap each in an
instance of some for-purpose custom exception.
[Alan:]
Righto. Was concerned about getting into the perpetually wrapped
exception with that. (Not being contrarian. Stating my concern.)

If you don't want to wrap then discard the original exception instead.
I don't see how it's useful to gratuitously dump potentially valuable
data, but you can do it if it better suits your sensibilities.
Um, okay, a valid design reason is to say, we think you should
design your own exception heirarchy, we can't anticiplate your
needs, but we've atomized it for you. If you use it once or
twice in your program, here's what you need to worry about. If
you're writing a reflective application, then think of an
exception handling strategy approprite for your application.

I was being a bit flippant, sorry. Reflection seems to hold an
unhealthy fascination for some people, so I and some others here tend to
discourage its use. Wherever you can avoid or minimize your use of
reflection you are better off. As for the exceptions thrown by
Method.invoke(), there are two general cases:
[snip]

By breaking down the situation this way, the Reflection API gives
you the opportunity to handle each distinct situation in a manner
appropriate for your application. You only need explicit handling
for the two checked exceptions: IllegalAccessException and
InvocationTargetException. You would need at least the latter, or
something like it, in any generic reflection-type API.

There are also the exceptions on the getMethod(s) and
getConstructor(s) methods. These are obvously part of the
reflection bit of your break down. They are checked, because
they would have been checked by the compiler.
The API is not nagging you: it is simply exhibiting its own
nature.
Agreed.


What's wrong with the API you already have?

I was beeing a bit flippant, sorry. I understand now that you
were trying to catch me before I went off down a blind ally. Thank you.

I'm really trying to avoid a making a discussion of when to use
a necessary step before a discussion on how to use, so I'm going
to fork my response.

Assume that I've made a valid decision to employ data-driven
reflection in to solve two separate problems.

I've run into a number of tasks that are repetitions. I'd like
to encapsulate those tasks in a library.

As far as what's wrong, the API I already have, the exception
heirarchy does not make the obvious distinction between erros in
reflection, and errors in the execution of a method invoked by
reflection.

I was thinking that I might create an error handler interface
that would be attached to a class loader, and that it would raise
unchecked exceptions, the sort that the application might
expect, but now a revised object heirarchy seems to make more
sense. One that would include more information about the failure.
 
C

Chris Smith

That last part is another thing that has been a cause for
consideration for me lately. What good is exception handling if
you do not provide the information necessary to fix the
exception? Why FileNotFoundException cannot have a getFile() method?

Basically, if you need it then you're doing something wrong. If you do
intend to recover from a file that's not found, then the try/catch block
that catches FileNotFoundException should be limited enough that only
one File is opened within that block. That's the one that wasn't found.

If, on the other hand, you write exception handling for large sections
of code that open several files, then you're going to have a really
tough time recovering and trying again to open the file that failed.
Essentially, the answer is to write smaller try blocks.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
A

alan

(e-mail address removed) wrote:
Testing, yes. JUnit is one of the examples I was thinking of. Do
note, however, that even in JUnit reflection is only used behind
the scenes to provide convenience features to the test writer.

Duely noted.

Most of what happens in an API or applicaton happens behind the
scenes. That falls under encapsulation.
...application frameworks...
It is rarely necessary to design a regular application this way.

Eh, well, many applications have a configuration aspect, without
being frameworks.

One could simply use BeanShell to create configuration files,
and once again, your point is made.

But if I don't want to ship BeanShell, I simply want to read a
few properties files, ala, Log4J, then I'm using reflection
myself, in an application. It is valid use.

Reflection provides a means to introduce components into an
exsiting application. It has to start with newInstance(), at
least because the type is not available.
Both of those are commonly _used_ types of applications, but they
are not commonly _written_ types of applications. I stand on my
position (clarified) that it is rare to need to use reflective
method invocation in an application, that doing so is vastly
inferior to using normal method invocation when that is possible,
and that therefore reflective method invocation is almost always a
sign of poor application design or implementation.

In light of the point I made above? Log4J is not a framework. It
is extensible, however. Can you see how plugins require reflection?
Do note that it is possible to reflectively instantiate classes but
invoke methods on them normally. This is what a well-designed plug-in
type API will do; I believe Ant's custom tasks are an example, and JDBC
drivers certainly are. This is the sort of use that I generally think
of in support of custom application configuration, and is not covered by
my arguments against reflective method invocation.

Oh, yes, you can see how plugins require reflection, sorry.

Well, then, reflection for bootstrapping is a common
application.

Once things are rolling, I'm against the use of instanceof.

I prefer to program with interfaces and object compostion. The
problem becomes one of assembling a lot of little objects.

Reflection is one way to handle this, so long as the assemblage
takes place infrequently. Jetty uses reflection to basically
build a server from component parts.

Keeping in mind that, if you have a pluggable architecture, and
you want to be acommodating, reflection might worm it's way into
parts of the program. The design pattern is that of the
scriptable component.

That properties file that says how to instanciate the Foo
plugin, might have also have a few lines on how to make it
frobnicate. A JSP page will reflect every time it runs to invoke
the getters and setters on the partipating Beans.

I'm not buying into these distinctions you are making. I don't
see applications as being a programming terminus, where parts of
the Java API off limits because they are too frameworky.

Any body of software will grow until the point where it is
pluggable (and can read e-mail).
 
A

alan

Basically, if you need it then you're doing something wrong. If you do
intend to recover from a file that's not found, then the try/catch block
that catches FileNotFoundException should be limited enough that only
one File is opened within that block. That's the one that wasn't found.
If, on the other hand, you write exception handling for large sections
of code that open several files, then you're going to have a really
tough time recovering and trying again to open the file that failed.
Essentially, the answer is to write smaller try blocks.

public void fooHandler implements org.xml.sax.ContentHandler {
public void startElement(String ns, String ln, String qn, Attributes as)
throws SAXException {
FileInputStream in = null;
do {
try {
String fileName = as.getValue("foo-file");
in = new FileInputStream(new File(fileName));
} catch (FileNotFoundException e) (
errorHandler.fatalError(new SAXParseException(e));
}
} while (in == null);
}
}

Something being considered on xml-dev.

The errorHandler can raise the SAXParseException. The errorHandler could
copy a dummy file into the position and continue processing, but it needs
the file name to do so.

If FileNotFoundException had a getFile() method, this would work, but
alas, it doesn't, an it don't.

This is a shortcoming of exceptions in general. There are times when
smaller try blocks won't work, because the exception handling logic and
the point of failure are separated by a messaging conduit (like
reflection), and might not even share a call stack.
 
C

Chris Smith

public void fooHandler implements org.xml.sax.ContentHandler {
public void startElement(String ns, String ln, String qn, Attributes as)
throws SAXException {
FileInputStream in = null;
do {
try {
String fileName = as.getValue("foo-file");
in = new FileInputStream(new File(fileName));
} catch (FileNotFoundException e) (
errorHandler.fatalError(new SAXParseException(e));
}
} while (in == null);
}
}
The errorHandler can raise the SAXParseException. The errorHandler could
copy a dummy file into the position and continue processing, but it needs
the file name to do so.

If FileNotFoundException had a getFile() method, this would work, but
alas, it doesn't, an it don't.

You're acting quite helpless about the whole thing, when you've clearly
just caught and rethrown an exception. You could rethrow any exception
you so desire. Why not wrap it in an exception that knows what file is
missing? That's a reasonable piece of information for a SAXException to
have, but superfluous for a FileNotFoundException, which is thrown in
response to an attempt to open a specific file. You are wrapping the
exception (exactly as you should), and you should include the additional
information when wrapping it.
This is a shortcoming of exceptions in general.

It's quite explicitly not a shortcoming of exceptions in general. It is
quite possible to define an exception containing any information you
want it to contain. If you want an exception with additional
information, then define one and put the information there.
There are times when
smaller try blocks won't work, because the exception handling logic and
the point of failure are separated by a messaging conduit (like
reflection), and might not even share a call stack.

Nope. As long as you stick to the abstraction, smaller try blocks will
always be suitable.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
A

alan

You're acting quite helpless about the whole thing, when you've clearly
just caught and rethrown an exception. You could rethrow any exception
you so desire. Why not wrap it in an exception that knows what file is
missing? That's a reasonable piece of information for a SAXException to
have, but superfluous for a FileNotFoundException, which is thrown in
response to an attempt to open a specific file. You are wrapping the
exception (exactly as you should), and you should include the additional
information when wrapping it.

Fair enough. I can create a new FileNotFoundExceptoin2 class
that contains the information relevent to the event, the missing
file name. The exception is acting, then, not as message, but as
a flag, for a particular type of error, I am responsible for
creating a proper event object.
It's quite explicitly not a shortcoming of exceptions in general. It is
quite possible to define an exception containing any information you
want it to contain. If you want an exception with additional
information, then define one and put the information there.

Okay. I mis-spoke. I think that exception handling would be more
robust of API designers would design their exception objects to
be more like objects that contain context information. Handling
exceptions at the point of call means that they are often
negelcted. There should also be a distinction drawn between
handling the exceptional condition, and the restoration of objec
tstate.
Nope. As long as you stick to the abstraction, smaller try blocks will
always be suitable.

In that case, it is not an abstraction, it is merely a language
construct. A block is a block, true, can't argue with that.
 
A

alan

In that case, it is not an abstraction, it is merely a language
construct. A block is a block, true, can't argue with that.

Actually, the more I think about it, the more the observer pattern strikes
me as the correct abstration for error handling.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top