[jboss-dev-forums] [Design of POJO Server] - Using AnnotationEnvironment in Seam
alesj
do-not-reply at jboss.com
Tue Aug 19 08:12:03 EDT 2008
I'll describe a bit how AnnotationEnvoroment works, where it comes from, ...
but then it should be up to Seam guys to fully incorporate this into Seam's
component scanning / lookup.
AnnotationEnv API:
| public interface AnnotationEnvironment
| {
| /**
| * Does this annotation environment contain a class
| * which is annotated with annotation parameter.
| * This only applies to annotations for ElementType.TYPE level.
| *
| * This method should be used if we have no intention
| * to do real lookup of annotated classes, but we're
| * only interested in existance of the annotation.
| * e.g. deployment unit contains @Stateful EJBs
| *
| * @param annotation the annotation we're querying for
| * @return true if there exists a class with annotation param
| * @see #hasClassAnnotatedWith(Class annotation)
| */
| boolean hasClassAnnotatedWith(Class<? extends Annotation> annotation);
|
| /**
| * Does this annotation environment contain a class
| * which is annotated with annotation parameter.
| * This only applies to annotations for ElementType.TYPE level.
| *
| * This method should be used if we have no intention
| * to do real lookup of annotated classes, but we're
| * only interested in existance of the annotation.
| * e.g. deployment unit contains @Stateful EJBs
| *
| * @param annotationName the annotation name we're querying for
| * @return true if there exists a class with annotation param
| * @see #hasClassAnnotatedWith(Class annotation)
| */
| boolean hasClassAnnotatedWith(String annotationName);
|
| /**
| * Get all classes annotated with annotation param.
| *
| * @param <A> the annotation type
| * @param annotation the annotation we're querying for
| * @return set of matching classes
| */
| <A extends Annotation> Set<Element<A, Class<?>>> classIsAnnotatedWith(Class<A> annotation);
|
| /**
| * Get all classes annotated with annotation param.
| *
| * @param annotationName the annotation name we're querying for
| * @return set of matching classes
| */
| Set<Element<Annotation, Class<?>>> classIsAnnotatedWith(String annotationName);
|
| /**
| * Get all classes who have some constructor annotated with annotation param.
| *
| * @param <A> the annotation type
| * @param annotation the annotation we're querying for
| * @return set of matching classes
| */
| <A extends Annotation> Set<Element<A, Constructor<?>>> classHasConstructorAnnotatedWith(Class<A> annotation);
|
| /**
| * Get all classes who have some constructor annotated with annotation param.
| *
| * @param annotationName the annotation name we're querying for
| * @return set of matching classes
| */
| Set<Element<Annotation, Constructor<?>>> classHasConstructorAnnotatedWith(String annotationName);
|
| /**
| * Get all classes who have some field annotated with annotation param.
| *
| * @param <A> the annotation type
| * @param annotation the annotation we're querying for
| * @return set of matching classes
| */
| <A extends Annotation> Set<Element<A, Field>> classHasFieldAnnotatedWith(Class<A> annotation);
|
| /**
| * Get all classes who have some field annotated with annotation param.
| *
| * @param annotationName the annotation name we're querying for
| * @return set of matching classes
| */
| Set<Element<Annotation, Field>> classHasFieldAnnotatedWith(String annotationName);
|
| /**
| * Get all classes who have some method annotated with annotation param.
| *
| * @param <A> the annotation type
| * @param annotation the annotation we're querying for
| * @return set of matching classes
| */
| <A extends Annotation> Set<Element<A, Method>> classHasMethodAnnotatedWith(Class<A> annotation);
|
| /**
| * Get all classes who have some method annotated with annotation param.
| *
| * @param annotationName the annotation name we're querying for
| * @return set of matching classes
| */
| Set<Element<Annotation, Method>> classHasMethodAnnotatedWith(String annotationName);
|
| /**
| * Get all classes who have some method's/constructor's parameter annotated with annotation param.
| *
| * @param <A> the annotation type
| * @param annotation the annotation we're querying for
| * @return set of matching classes
| */
| <A extends Annotation> Set<Element<A, AnnotatedElement>> classHasParameterAnnotatedWith(Class<A> annotation);
|
| /**
| * Get all classes who have some method's/constructor's parameter annotated with annotation param.
| *
| * @param annotationName the annotation name we're querying for
| * @return set of matching classes
| */
| Set<Element<Annotation, AnnotatedElement>> classHasParameterAnnotatedWith(String annotationName);
| }
|
| public interface Element<A extends Annotation, M extends AnnotatedElement>
| {
| /**
| * Get the owner class name.
| *
| * Until we hit getOwner method the class should not be loaded.
| *
| * @return the owner classname
| */
| String getOwnerClassName();
|
| /**
| * Get the annotation owner class.
| *
| * @return the annotation owner class
| */
| Class<?> getOwner();
|
| /**
| * Get the annotation instance.
| *
| * @return the annotation instance
| */
| A getAnnotation();
|
| /**
| * Get the annotated element that holds the annotation.
| *
| * @return the annotated element instance
| */
| M getAnnotatedElement();
| }
|
The API is pretty simple :-),
as can be seen it has to 'flavors',
one where you put direct annotation class as parameter,
the other one where you put annotation class name.
The Element has a few useful hooks,
and its impl detail is that it's completely lazy -
it doesn't load the class or annotation until asked.
There is a flag on the annotation scanning deployer,
that allows for AnnotationEnvironment to already keep
the annotation instance gathered from Javassist lookup -
meaning you don't even need to load the class to
inspect annotation value.
e.g. you only need classname + annotation member values
When (annotation scanning) deployers are properly configured,
this is already the case in current JBoss5 trunk,
every deployment unit gets AnnotationEnvironment as an attachment.
| DeploymentUnit unit = getAttribute(context, DeploymentUnit.class.getName(), DeploymentUnit.class);
| AnnotationEnvironment env = unit.getAttachment(AnnotationEnvironment.class);
|
In the Seam case we would have to do a bit of
hierarchy traversing to get all the AnnotationEnvironments,
from all deployment units, since we only have web deployment unit,
in the ServletContext attributes.
| public class JBossSeamListener extends SeamListener
| {
| public void contextInitialized(ServletContextEvent event)
| {
| // TODO - enable some MC scanning notion in Seam
| super.contextInitialized(event);
|
| ServletContext context = event.getServletContext();
| Kernel kernel = getAttribute(context, Kernel.class.getName(), Kernel.class);
| DeploymentUnit unit = getAttribute(context, DeploymentUnit.class.getName(), DeploymentUnit.class);
|
Looking at the ComponentDeploymentHandler::handle
| public void handle(String name, ClassLoader classLoader)
| {
| if (name.endsWith(".class"))
| {
| String classname = filenameToClassname(name);
| String filename = componentFilename(name);
| try
| {
| ClassFile classFile = getClassFile(name, classLoader);
| boolean installable = ( hasAnnotation(classFile, Name.class) || classLoader.getResources(filename).hasMoreElements() )
| && !"false".equals( getAnnotationValue(classFile, Install.class, "value") );
| if (installable)
| {
| log.trace("found component class: " + name);
| classes.add( (Class<Object>) classLoader.loadClass(classname) );
| }
|
Looks like we should also do a bit more than just looking for @Name,
but for the @Install::value==false it should be just a simple Set intersection.
Where I don't see what exactly does "classLoader.getResources(filename).hasMoreElements() " do/help.
Pete & co., if you need any other info,
post it here. :-)
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4171242#4171242
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4171242
More information about the jboss-dev-forums
mailing list