javapoet syntax example

Which framework to generate source code ?


I have been recently writings tools to convert Beanshell in Java. This is a technical post to compare some frameworks to generate source code.


How to generate source code ?

It exists several solutions that I would classify in three categories.

  • using a template engine
  • using an AST/Source to framework
  • others

Each solution has it drawbacks and strengths.

Template engine

Well with a template engine like Velocity or JET, you basically can write anything you want.

You won’t be constrained by an API and you may also generate syntaxic invalid files.

The main drawback is that you can’t write in a one shot your implementation. You will have to  store your template in your resources, write a to access it before generating your code.

Depending of the template engine, it can be a real pain.

public class HelloVelocity {
 public static void main(String[] args) {
// Boring  to initialize the template engine
 VelocityEngine ve = new VelocityEngine();
 ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
 ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());

 // Try to find the code template
 Template t = ve.getTemplate("codeTemplate.vm");
 VelocityContext ctx = new VelocityContext();
 // Initialize the context.
 ctx.put("name", "velocity");
 ctx.put("date", (new Date()).toString());
 List temp = new ArrayList();
 ctx.put("list", temp);
 StringWriter sw = new StringWriter();
 // Finally render
 t.merge(ctx, sw);

Using an AST/Source to source generator

I will present you an interesting framework based on JDT compiler.

This framework is called Roaster, is open-source and hosted on Github.

This is a maven library which provides a fluent API to generate java classes. Here an example:

final JavaClassSource javaClass = Roaster.create(JavaClassSource.class);


javaClass.addProperty(Integer.class, "id").setMutable(false);
javaClass.addProperty(String.class, "firstName");
javaClass.addProperty("String", "lastName");

  .setBody("this.id = id;")
  .addParameter(Integer.class, "id");

Where the framework differs, is that it relies on JDT. The source code (parsed or created programmatically is associated to a JDT Dom Tree). Basically we are using the Eclipse functionalities to the Java source and unparse it.

Next to read  Spring Boot and Liquidbase : how to change the default path and filename

Therefore, an hybrid approach can be chosen mixing parsing and programmation to produce your source code.

JavaClassSource javaClass =
  Roaster.parse(JavaClassSource.class, "public class SomeClass {}");
  .setBody("System.out.println(\"Hello World\");")
  .addParameter("java.lang.String[]", "args");

The main drawback of this solution is that I did not find any way to insert invalid java code (aka a plain String) into my class structure. The string is parsed by JDT and if its invalid, it throws an exception. Since I potentially have some invalid structures in Beanshell to be converted as Java, I have been blocked without solution.

Other frameworks

I want to present an outsider : JavaPoet.

This framework hosted on Github is half-way between a template engine and an AST generation framework,

JavaPoet is offering a nice Fluent interface to produce your Java source code.

All things are easy to understand and manipulate : structures, flow control statements, types.

MethodSpec main = MethodSpec.methodBuilder("main")
    .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
    .addParameter(String[].class, "args")
    .addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")

TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
    .addModifiers(Modifier.PUBLIC, Modifier.FINAL)

JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)


I have been using it in several projects and it’s possible to inject plain Strings directly inside a valid structure. Rather efficient (it generates the package folder structure for you), it has a main drawback, you cannot declare your own imports (at the exception of the static ones).

Therefore if  you are building your using a mix of  Fluent blocks and String templates, you will be soon short of imports to have a perfectly compiling code.

Next to read  Disruption in Software Quality Assessment, still relevant in 2021 ?

And you know what, they don’t want to add the feature grr :



Sylvain Leroy

Senior Software Quality Manager and Solution Architect in Switzerland, I have previously created my own company, Tocea, in Software Quality Assurance. Now I am offering my knowledge and services in a small IT Consulting company : Byoskill and a website www.byoskill.com Currently living in Lausanne (CH)

View all posts by Sylvain Leroy →