When I did this for OpenEJB I put the work into a neutral place (xbean) so it could be shared by anyone who needed it. XBean is sort of a common-like dumping ground for server-ish bits and pieces we were sharing between OpenEJB, ActiveMQ, ServiceMix, Geronimo, Maven and similar projects.

Between xbean-finder (secure ASM-based annotation scanner, resource finder, etc) and xbean-reflect there really isn't anything you can't do.

Most of the documentation for is javadoc. This post on TSS has a nice overview:

  http://www.theserverside.com/news/thread.tss?thread_id=49083#250760

The annotation scanner is org.apache.xbean.finder.ClassFinder[1]. That's implemented how you detail #1. We scan the byte-code via ASM to avoid the security risks, wasted permgen space, and time associated with classloading. We even have optimizations to avoid reading all the byte code which makes scanning pretty fast. We construct a small amount of metadata on the annotations we found and cache that so multiple searches can be done more or less free of cost.

It gets released pretty frequently[2] and getting patches in is easy.

-David

[1] 
http://svn.apache.org/repos/asf/geronimo/xbean/tags/xbean-3.4.3/xbean-finder/src/main/java/org/apache/xbean/finder/ClassFinder.java
[2] http://svn.apache.org/repos/asf/geronimo/xbean/tags/

On Jan 18, 2009, at 2:55 PM, Mark Struberg wrote:

+1 for a commons.annoscan

Concerning the question of how to design the API for this scanner:

Sometimes there is not a fixed set of annotations to scan for (like a.g. JPA) but one doesn't even a priori know which annotations are really important. In WebBeans any user may define it's own annotations in his custom project and define e.g. a custom @StereoType @AdministratorAction. So this is a highly dynamic situation and there are 3 ways to cope with it coming to my mind:

1.) scan for all annotations and store them all for later queries. (which is the scannotation+javassist way currently used in openwebbeans) 2.) multi-pass scanning (this would be more time consuming but has a small memory footprint)
3.) scan all annotations and remove all unnecessary ones.


LieGrue,
strub

--- Bernd Bohmann <bernd.bohm...@atanion.com> schrieb am So, 18.1.2009:

Von: Bernd Bohmann <bernd.bohm...@atanion.com>
Betreff: Re: Scanning for annotated classes in MyFaces 2
An: "MyFaces Development" <dev@myfaces.apache.org>
Datum: Sonntag, 18. Januar 2009, 22:00
Hello,

perhaps the annotation scanning was already solved by
openejb?
We should try to create a common annotation module for
apache projects
like openejb, tomcat, cxf and myfaces.

Regards

Bernd



Gerhard Petracek schrieb:
hello,

i agree with simon.

regards,
gerhard



2009/1/18 Simon Lessard
<simon.lessar...@gmail.com>

Hi again,

Actually, much more packages have to be scanned.
The goal of those
annotation is 0-Config, so a faces-config.xml
might not even be needed
anymore in the libraries. Anyway, before
implementing any kind of package
filter, I would wait for the final spec version,
as long as the scanner is
designed to easily include such filter if/when the
need arise.


Regards,

~ Simon


On Sun, Jan 18, 2009 at 11:15 AM, Cagatay Civici
<cagatay.civ...@gmail.com
wrote:
I also have some questions for the JSF 2.0 EG,
like what classpaths
need to be scanned by default. Or the
policy of dealing with runtime
invisible annotations (I can read them,
but Reflection cannot). I'm
also interested in general rules regarding
class/method signatures.
For example, do you need to implement a
specific interface when
annotating a class with @FacesComponent?

Afaik, only jars with a faces-config.xml under
META-INF are subject to
scan in classpath.

On Sun, Jan 18, 2009 at 4:01 PM, Jan-Kees van
Andel <
jankeesvanan...@gmail.com> wrote:

That sounds great.

What is your general approach? Just
read in the class as byte[], then
use the class-file-format rules to get
to the annotations sections on
the class and the methods? From my
quick scan of the classfile spec it
seemed reasonably easy to do that...

This line is the important one:
DataInputStream dis = new
DataInputStream(new BufferedInputStream(new
FileInputStream(classFile)));

The DataInputStream is responsible for
delivering the bytecode to me
as easy-to-read ints, shorts and bytes.
The first chapter of this document
specifies the relation between the
terms used in the spec and the
DataInputStream API.


http://java.sun.com/docs/books/jvms/second_edition/ClassFileFormat-Java5.pdf

From there it's just reading each
field, which is quite cumbersome and
hard to get right the first time, because
you need to read the spec
very carefully. For example, when reading
a double or long, you need
to skip the next byte. Forget this and you
get annoying errors, like
EOF or variables that contain nonsense.
But when you get the hang of it, it's
not that hard.

I'd be interested to know the
actual requirements that MyFaces has for
such a scanner. For example, does it
ever need to look for annotations
on methods when the class itself is
not annotated?

I also have some questions for the JSF 2.0
EG, like what classpaths
need to be scanned by default. Or the
policy of dealing with runtime
invisible annotations (I can read them,
but Reflection cannot). I'm
also interested in general rules regarding
class/method signatures.
For example, do you need to implement a
specific interface when
annotating a class with @FacesComponent?

Your comment about "expose parsed
classes" seems to imply that you are
providing some kind of DOM-style API.
I would have thought that a
SAX-style API would be better, ie
various bits of code interested in
annotations registers callbacks for
annotations it cares about with the
"scanner". Then the scanner
scans all jars in the classpath and when
something is found that matches a
"registered" annotation, then it
invokes the appropriate callback. That
approach would minimise memory
usage, and I can't see where we
would need anything dom-like...
Well, for performance reasons you would
like a SAX style API, but
afaics, the class file format is not very
developer friendly. Maybe it
just takes some getting used to, but on
first sight, it looks less
intuitive than SAX parsing an XML
document. For example, class
attributes are placed below the fields and
methods, so you don't know
the class annotations when reading through
the fields and methods.
That's not very intuitive for a
developer.

My plan was not to fully initialize the
classes, but just fill them
with the bytes read. This way, I get a
little bit more structure so I
don't have to think in bits and bytes
too much. The heavy work will be
done lazily. For example, I don't
initialize the classes' fields
unless the user asks for it, probably
resulting in less memory usage
and better performance than a fully
fledged DOM model.

But there's only one way to find out
and that's implementing and testing
it.

I'm gonna look at a SAX style API.
Maybe it's not as bad as I first
thought...

Regards,

/Jan-Kees









Reply via email to