6

We have a library of Java code that we intend to use across projects. Some of these projects will require having annotations added to the Java objects in this library (i.e. in one project, these objects will be used in a JAX-RS servlet implementation so they need to be annotated with JAXB, JSON etc annotations). The issue I am having is that I could not figure out how to add these annotations without changing the original library.

Consider this example:

public class MyClass
{
    private String field1;
    private int field2;
}

In some projects, I would like the class to behave as if it was

public class MyClass
{
    @Annotation1
    private String field1;
    @Annotation2
    private int field2;
}

Initially I thought about using interfaces or derived classes that are separately annotated but could not figure out how to do it (or whether it is possible or not). I also found about the Javassist suggestion in this thread (i.e. Java bytecode manipulation approach) but the issue is that this needs to work on Android clients as well so it is not an option for me. At this point I am out of ideas.

I would appreciate if someone could help in any way. Maybe I am missing something, or maybe what I am trying to do is not the right way. In any case, I need some guidance now in order to proceed.

Thanks very much in advance.

Community
  • 1
  • 1
alokoko
  • 1,405
  • 4
  • 21
  • 35
  • What is the problem with changing the original library? It's your code, near as I can tell. – CommonsWare Sep 04 '11 at 15:29
  • The library manages a bunch of objects, their collections and the in-memory CRUD functionality (constraints, validation etc). It does not have any knowledge of serialization and persistence of these objects, and I would like to keep those separate. Also, unavailable annotations may cause problems on the target platform: Android does not have the JAXB annotations and any framework that processes annotations fail on Android even though JAXB annotations are not being used (NoClassDefFoundError). I would like to avoid adding annotations if they are not going to be used by the target platform. – alokoko Sep 04 '11 at 18:36

2 Answers2

4

I looked into this more and as a summary, here's what I found:

  • Java language does not allow changing annotations during runtime.
  • One can use Javassist to modify the java bytecode but it does not work on platforms like Android.
  • One can use ASM but that involves dealing with Java assembly (an example is here: http://community.jboss.org/thread/150002).

Primarily due to JAXB not being present on Android (and other reasons) we switched to JSON and starting using Jackson as the implementation. One benefit of this change was the ability to use what Jackson calls "mixed-in annotations" which is exactly what I was looking for.

Here's the link that explains it more: http://www.cowtowncoder.com/blog/archives/2009/08/entry_305.html

alokoko
  • 1,405
  • 4
  • 21
  • 35
0

Short of hacking the .class bytecode during runtime, this can't be done. You can use Javassist if you really want to dynamically change the bytecode of the library classes during runtime but in the bigger picture this will probably end up blowing up badly.

I would suggest that you just annotate the library and recompile if its your codebase. If it isn't, you can still wrap the library classes/interfaces in your own classes/interfaces through inheritance and annotate there. Either way, I think it would be better to annotate in the code than through runtime bytecode hacking. Added bonus, annotations in the source will be seen by IDEs, allowing the IDE to better assist you.

  • See my comment to the question. I already know about Javassist but I need it work on the Android platform as well and Javassist does not work on Android. – alokoko Sep 04 '11 at 18:39