4

I am currently building an API that I will be asking a number of developers to use. Most of it is straightforward, but there are a couple of api calls that are complex in nature, but should be used in pretty much a boilerplate way.

What I would like to do is to generate the boilerplate code inside of the classes, maybe by marking some annotations, but those generated methods to be available within Eclipse/IntelliJ for the developer to see. I looked at Javassist, but not sure that the runtime nature is a good thing. I would rather a compile time approach.

If possible, I would like the implemented code to be hidden (i.e. I don't want the developers to try to change the code of the generated methods, as they will be over written on recompile).

This whole thing is done in an effort to hide the complexity of the processing away from the developers and maintainers, and keep it in the core framework code only.

Codemwnci
  • 54,176
  • 10
  • 96
  • 129
  • Generated code is pretty standard. For example, JAXB has XJC - which compiles XML schemas into Java classes, and it's in the Java standard library. I suppose the "interesting" part of this would be integrating generating the code into your build system - I use Maven, and it makes doing this pretty straight-forward. – cha0site Jun 26 '12 at 18:08
  • 1
    I would start by implementing what you want with reflections and optimise it if you need to with generated code. – Peter Lawrey Jun 26 '12 at 18:08

2 Answers2

5

There are two parts to this question. First, you want to make the API available to developers without writing/exposing boilerplate implementation. Second, you want to automate the generation of the boilerplate code.

If you are willing to acknowledge that some framework is being used, you can do this without code/bytecode generation:

  • For each important concept, write an interface that fully defines the API.
  • Now write the corresponding class that does not implement the interface, but matches the method signatures of the non-boilerplate APIs. You may want to use a naming convention to pair these up.
  • Write a factory that generates implementations of the interface using Java Proxies. The proxy would delegate to the implementation whenever possible. The boilerplate code would be implemented directly in the implementation handler.
  • You may need various types of invocation handlers, in that case, consider a naming convention for those as well
  • If you don't like the unchecked coupling between logic and interface, extract a super-interface that does not contain the boilerplate APIs.
  • The logic that uses these constructs will ask for instances by interface name; the factory would know how to instantiate the underlying logic instance and the invocation handler.

On the other hand, if you don't want your developers to remember the existence of the framework, or you need the boilerplate implementations to have access to the internals of the logic, then you need to do code generation / bytecode manipulation.

The manipulation itself can be done using a custom classloader, or during initial classloading using Java Agents. But how do you make the API available to developers? Here are some ideas:

  • Make the implementation classes abstract, and declare abstract methods where boilerplate code will be generated.

  • Write stub implementations of the boilerplate methods (i.e. do nothing in void methods; throw RuntimeException in all others.) Mark these methods with some annotation.

  • Do something like what Google Web Toolkit does, and declare the boilerplate methods as native. This is similar to marking the methods abstract, but allows you to do things like making classes final.

Dilum Ranatunga
  • 13,254
  • 3
  • 41
  • 52
0

The Java compiler has support for annotation processing. You could write your own processors that would generate code as required by your annotations.

Edwin Dalorzo
  • 76,803
  • 25
  • 144
  • 205
  • 3
    unfortunately, this will only allow the creation of new source files, and not the reconstruction of the annotated source file. – Codemwnci Jun 26 '12 at 18:27