Search code examples
javareflectionplayframeworkjavassist

Getting javassist class with playframework


I'm trying to obtain CtClass reference to my model class. I started with simpliest version ClassPool.getDefault().get(className); and it worked fine. But only on my machine. It doesn't work on server.

Anyway i think that the version shouldn't work because Playframework stores classes in tmp/classses. So by now i finished with this version:

ClassPool pool = new ClassPool();
pool.appendClassPath(Play.applicationPath + "/tmp/classes");
CtClass cls = pool.get(className);

But i am not sure about this version. Will it work always? Are there better options?

I also tried using ClassClassPath and LoaderClassPath but without any success.


Solution

  • Usually you should not touch javassist class unless you are writing plugin and need to enhance the application code. in which case, you will have a MyPluginEnhancer extends play.classloading.enhancers.Enhancer, then you can get the javassist class instance by calling makeClass(ApplicationClass appClass) method.

    For a workable example, please refer to https://github.com/greenlaw110/play-morphia/blob/master/src/play/modules/morphia/MorphiaEnhancer.java.

    PS: About play.classloading.enhancers.Enhancer.makeClass method implementation

    /**
     * Construct a javassist CtClass from an application class.
     */
    public CtClass makeClass(ApplicationClass applicationClass) throws IOException {
        return classPool.makeClass(new ByteArrayInputStream(applicationClass.enhancedByteCode));
    }
    

    Where classPool comes from the following code:

    public Enhancer() {
        this.classPool = newClassPool();
    }
    
    public static ClassPool newClassPool() {
        ClassPool classPool = new ClassPool();
        classPool.appendSystemPath();
        classPool.appendClassPath(new LoaderClassPath(Enhancer.class.getClassLoader()));
        classPool.appendClassPath(new ApplicationClassesClasspath());
        return classPool;
    }