29
Annotation Processing Tool in real life example

Annotation processing tool

Embed Size (px)

Citation preview

Annotation Processing Toolin real life example

Annotation Processing Tool

Andrzej LudwikowskiR&D Eurobankaludwikowski.blogspot.comgithub.com/[email protected]

in real life example

Agenda

Use caseWhat is APT?How to use it?How to implement it?How to debug it?In practice

How to prepare collaborators? public class Order {  private List<OrderItem> items; private Date createDate; private boolean realized;

 //other DDD methods

 public void orderRealized(){  //very complex implementation  realized = true; }

public boolean isRealized(){  return realized; }

}

Builder vs mock

Builder vs mock

Order realizedOrder = anOrder().realized().build();

Order realizedOrder = mock(Order.class);given(realizedOrder.isRealized()).willReturn(true);

HackingBuilder

HackingBuilder

For tests only !!!

Builder implementation public class Order {  private List<OrderItem> items; private Date createDate; private boolean realized;

 //other DDD methods

 public void orderRealized(){  //very complex implementation  realized = true; }

public boolean isRealized(){  return realized; }

}

Builder implementation public class Order { private List<OrderItem> items; private Date createDate; private boolean realized;

public void orderRealized() { // very complex implementation realized = true; }

public static OrderBuilder anOrder() { return new OrderBuilder(); }

public static class OrderBuilder { private final Order order = new Order();

public OrderBuilder withItems(List<OrderItem> items) {...} public OrderBuilder withCreateDate(Date createDate) {...} public OrderBuilder withRealized(boolean realized) {...} public OrderBuilder realized() {return withRealized(true);}

public Order build() { return order; } }}

Builder implementation public class Order { private List<OrderItem> items; private Date createDate; private boolean realized;

public void orderRealized() { // very complex implementation realized = true; }

public static OrderBuilder anOrder() { return new OrderBuilder(); }

public static class OrderBuilder { private final Order order = new Order();

public OrderBuilder withItems(List<OrderItem> items) {...} public OrderBuilder withCreateDate(Date createDate) {...} public OrderBuilder withRealized(boolean realized) {...} public OrderBuilder realized() {return withRealized(true);}

public Order build() { return order; } }}

Reflection + dynamic proxy

Builder implementation public abstract class OrderBuilder extends AbstractBuilder<Order,

OrderBuilder>{  public abstract OrderBuilder withItems(List<OrderItem> items); public abstract OrderBuilder withCreateDate(Date createDate); public abstract OrderBuilder withRealized(boolean realized);

 public static OrderBuilder anOrder(){  return AbstractBuilderFactory.createImplementation(OrderBuilder.class); }

}

Builder implementation public abstract class OrderBuilder extends AbstractBuilder<Order,

OrderBuilder>{  public abstract OrderBuilder withItems(List<OrderItem> items); public abstract OrderBuilder withCreateDate(Date createDate); public abstract OrderBuilder withRealized(boolean realized);

public OrderBuilder realized() {  Order order = targetObject();  order.orderRealized();  // other methods  return builder(); }

 public static OrderBuilder anOrder(){  return AbstractBuilderFactory.createImplementation(OrderBuilder.class); }

}

Builder separation public abstract class AbstractOrderBuilder<B> extends

AbstractBuilder<Order, B> {

 public abstract B withItems(List<OrderItem> items); public abstract B withCreateDate(Date createDate); public abstract B withRealized(boolean realized);

}public abstract class OrderBuilder extends AbstractOrderBuilder<OrderBuilder> {

 public static OrderBuilder anOrder() {  return AbstractBuilderFactory.createImplementation(OrderBuilder.class); }

 public OrderBuilder realized() {  Order order = targetObject();  order.orderRealized();  return builder(); }}

Generation Gap public abstract class AbstractOrderBuilder<B> extends

AbstractBuilder<Order, B> {

 public abstract B withItems(List<OrderItem> items); public abstract B withCreateDate(Date createDate); public abstract B withRealized(boolean realized);

}public abstract class OrderBuilder extends AbstractOrderBuilder<OrderBuilder> {

 public static OrderBuilder anOrder() {  return AbstractBuilderFactory.createImplementation(OrderBuilder.class); }

 public OrderBuilder realized() {  Order order = targetObject();  order.orderRealized();  return builder(); }}

http://martinfowler.com/dslCatalog/generationGap.html

Metamodel JPA @Generated(value =

"org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")@StaticMetamodel(Order.class)public abstract class Order_ {

public static volatile SingularAttribute<Order, Integer> id; public static volatile ListAttribute<Order, OrderItem> items; public static volatile SingularAttribute<Order, Date> createDate; public static volatile SingularAttribute<Order, Boolean> realized;

}

What is APT?The command-line utility apt, annotation processing tool, finds and executes

annotation processors based on the annotations present in the set of

specified source files being examined. The annotation processors use a set of reflective APIs and supporting infrastructure to perform their processing of program annotations

(JSR 175). The apt reflective APIs provide a build-time, source-based, read-only view of program structure. These reflective APIs are designed to cleanly model the JavaTM programming language's type system after the addition of generics (JSR 14). First, apt runs annotation processors that can produce new source code and other files. Next, apt can cause compilation of both original and generated source files, thus easing the development cycle.

What is it for?• source code generation (metamodel, fluentbuilder, e.t.c)• config file generation (maven-scr-plugin)• ...

How to use it?• javac -proc:none/-proc:only -processor ...• META-INF/services/javax.annotation.processing.Processor• ant• maven (maven-processor-plugin)• gradle• Eclipse, IntelliJ, ...

How to implement it?• @SupportedAnnotationTypes( *, foo.bar.Baz, foo.bar.*)

How to implement it?• @SupportedAnnotationTypes( *, foo.bar.Baz, foo.bar.*)• Lifecycle: scan, compile, recursive scan of generated sources, listeners after each round

How to implement it?• @SupportedAnnotationTypes( *, foo.bar.Baz, foo.bar.*)• Lifecycle: scan, compile, recursive scan of generated sources, listeners after each round

package example;public class Order {

 Date createDate;  

 public Order() {}

 public void orderRealized(){  //very complex implementation  realized = true; }}

Element

TypeMirror

visitor

How to debug it?• System.out.println()

How to debug it?• System.out.println()• Messager

How to debug it?• System.out.println()• Messager• Eclipse plugin

How to debug it?• System.out.println()• Messager• Eclipse plugin• debug on build

In practice• take existing implementation and use it (only the good parts)• documentation sucks• m2e sucks• only one output folder? • dependecies -> uber-jar• never put your surname in the package name

fluentbuilder

• automatic incremental builder generation• separation from the production code• no setters needed• ability to add custom, specific for domain, building methods

• file renames not supported• ???

Pros:

Cons: