How to scan java project to detect Annotations and execute on web application starts.


Java Annotation
Java Annotation

Java annotation is an important feature introduced in Java 1.5. You can see Hello World with Java annotation here. It makes your configuration so easy and execute code in runtime. All the major frameworks from Spring to Hibernate using Annotations effectively to load their framework. In this article we will see how we can create a custom annotation and execute it dynamically at run time using java byte code analysis.

Why we need byte code analyzer?

Well, it is practically resource consuming task to load each and every class using ClassLoader in to memory and analysis it. So the better way is to use java byte code analyzer. Instead of loading class, byte code analyzers takes the generated java byte code. It makes faster and less resource consuming. In this example we will use JavaAssist, where there are other byte code analyzers also available such ASM, Apache Common BCEL etc.

Step 1:

Maven configuration to include dependencies.

<dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.12.1.GA</version>
 </dependency>

Step 2:

Add a simple annotation

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface initCache {
}

Step 3:

use this Annotation in any of the method, say like


public class Test{
    @initCache
    public void testMe() {
        System.out.println("annotation working fine");
    }
}

Step 4:

Register a ContextAware Listener with the web.xml

<listener>
        <listener-class>
            org.test.init.context.ProjectInitializer.java
        </listener-class>
    </listener>

Step 5:

Write implementation on ProjectInitializer.java

public class MedPlotFrameworkInitializer implements ServletContextListener {
    
    ServletContext context;
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        context = servletContextEvent.getServletContext();        
        List<String> urlsList = new ArrayList<String>();
        Set libJars = context.getResourcePaths("/WEB-INF/lib");

        for (Object jar : libJars)
        {
            try
            {

                urlsList.add(context.getRealPath((String)jar));

            }
            catch (Exception e)
            {
                throw new RuntimeException(e);
            }

        }

        execute(urlsList);
        

    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
       
    }

    public static void execute(List<String> urlList) {


        try {

            for (String url : urlList) {

                JarFile jarFile = new JarFile(url);
                Enumeration<JarEntry> entries = jarFile.entries();
                while (entries.hasMoreElements()) {
                    JarEntry entry = entries.nextElement();
                    if (entry.getName().endsWith(".class")) {
                        InputStream is = jarFile.getInputStream(entry);
                        DataInputStream dstream = new DataInputStream(new BufferedInputStream(is));
                        ClassFile cf = new ClassFile(dstream);
                        List<MethodInfo> methodList = cf.getMethods();
                        for (MethodInfo method : methodList) {
                            AnnotationsAttribute visible = (AnnotationsAttribute) method.getAttribute(AnnotationsAttribute.visibleTag);
                            if (visible != null) {
                                for (Annotation ann : visible.getAnnotations()) {
                                    if (ann.getTypeName().equalsIgnoreCase(THREAD_ANNOTATION_MARKER) || ann.getTypeName().equalsIgnoreCase(CACHE_ANNOTATION_MARKER)) {
                                        Class<?> c = Class.forName(cf.getName());
                                        Object obj = c.newInstance();
                                        Method m = c.getDeclaredMethod(method.getName());
                                        m.invoke(obj, null);
                                        
                                    }

                                }
                            }

                        }

                    }
                }
            }


        } catch (IOException ioe) {
           ioe.printStackTrace();
        } catch (Exception use) {
            use.printStackTrace();
        }

    }
}

This will scan all you lib folder jar files and execute the annotation.

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s