87
Marvel of Annotation by Alexey Buzdin Preprocessing

Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Embed Size (px)

Citation preview

Page 1: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Marvel of Annotationby Alexey BuzdinPreprocessing

Page 2: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

@AlexeyBuzdin

GDGRiga.lv RigaDevDay.lv

Page 3: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

๏ What? ๏ Why? ๏ How? ๏ Dagger ๏ Lombok ๏ MapStruct ๏ Retrofit

Page 4: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

๏ What? ๏ Why? ๏ How? ๏ Dagger ๏ MapStruct ๏ Retrofit ๏ Lombok

Page 5: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

“Developer loves to write code”

Page 6: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

“Developer loves to write code”

- noone ever

Page 7: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

“Developer loves complex tasks”

Page 8: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

“Developer loves complex tasks”

- probably you

Page 9: Marvel of Annotation Preprocessing in Java by Alexey Buzdin
Page 10: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

CRUD

Page 11: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

CRUD- api - type: XML, JSON - resources - /clients - access: R - entity 🔑 clientId - full name - email - /payments - entity 🔑 paymentId 🔑 clientId | link - amount - db: jdbc:mysql://localhost:3306/crudapp

Page 12: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

CRUD- api - type: XML, JSON - resources - /clients - access: R - entity 🔑 clientId - full name - email - /payments - entity 🔑 paymentId 🔑 clientId | link - amount - db: jdbc:mysql://localhost:3306/crudapp

Authentication?

Page 13: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

CRUD- api - type: XML, JSON - resources - /clients - access: R - entity 🔑 clientId - full name - email - /payments - entity 🔑 paymentId 🔑 clientId | link - amount - db: jdbc:mysql://localhost:3306/crudapp - ldap: ldap://ldap.example.com/dc=example,dc=com

Page 14: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

never let go of yourD R E A M S

Page 15: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

In Practice

Page 16: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

In PracticeRouting XML, JSON Building Response

Page 17: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

public class SimpleServlet extends GenericServlet { public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { // do something in here } }

Generic Servlet

Page 18: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

In PracticeRouting XML, JSON Building Response

Page 19: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

In PracticeMap Validate

Routing XML, JSON Building Response

Page 20: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

In PracticeConstruct Query

Map Validate

Routing XML, JSON Building Response

Page 21: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Reflection and Runtime Code Generation

Everywhere!Spring, Hibernate, GSON, Jersy, Dozer,

Guice, Weld, etc…

Page 22: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Reflection - Slow?

Page 23: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Reflection - Slow?

http://docs.oracle.com/javase/tutorial/reflect/index.html

Performance OverheadBecause reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.

Page 24: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Reflection - Slow?

http://docs.oracle.com/javase/tutorial/reflect/index.html

Performance OverheadBecause reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.

Page 25: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Reflection - Slow?

http://docs.oracle.com/javase/tutorial/reflect/index.html

Performance OverheadBecause reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.

Page 26: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Code Generation?

https://zeroturnaround.com/rebellabs/how-to-make-java-more-dynamic-with-runtime-code-generation/

Page 27: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Code Generation?

https://zeroturnaround.com/rebellabs/how-to-make-java-more-dynamic-with-runtime-code-generation/

Generates Java Bytecode at Runtime

Page 28: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Code Generation?

https://zeroturnaround.com/rebellabs/how-to-make-java-more-dynamic-with-runtime-code-generation/

Generates Java Bytecode at Runtime

Not always ok

Page 29: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Code Generation?

https://zeroturnaround.com/rebellabs/how-to-make-java-more-dynamic-with-runtime-code-generation/

GWT, Android, j2objc, RoboVM, code transpilers

Doesn’t work

Page 30: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Annotation Processing

Page 31: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Annotation Processing

A tool build in javac for scanning and processing annotations at compile time

Page 32: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

How?public class MyProcessor extends AbstractProcessor {

@Override public synchronized void init(ProcessingEnvironment env){ } @Override public boolean process(

Set<? extends TypeElement> annotations, RoundEnvironment env) { } @Override public Set<String> getSupportedAnnotationTypes() { } @Override public SourceVersion getSupportedSourceVersion() { }

}

http://hannesdorfmann.com/annotation-processing/annotationprocessing101/

Page 33: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

How?public class MyProcessor extends AbstractProcessor {

@Override public synchronized void init(ProcessingEnvironment env){ } @Override public boolean process(

Set<? extends TypeElement> annotations, RoundEnvironment env) { } @Override public Set<String> getSupportedAnnotationTypes() { } @Override public SourceVersion getSupportedSourceVersion() { }

}

http://hannesdorfmann.com/annotation-processing/annotationprocessing101/

Page 34: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

How?public class MyProcessor extends AbstractProcessor {

@Override public synchronized void init(ProcessingEnvironment env){ } @Override public boolean process(

Set<? extends TypeElement> annotations, RoundEnvironment env) { } @Override public Set<String> getSupportedAnnotationTypes() { } @Override public SourceVersion getSupportedSourceVersion() { }

}

http://hannesdorfmann.com/annotation-processing/annotationprocessing101/

Page 35: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

How?public class MyProcessor extends AbstractProcessor {

@Override public synchronized void init(ProcessingEnvironment env){ } @Override public boolean process(

Set<? extends TypeElement> annotations, RoundEnvironment env) { } @Override public Set<String> getSupportedAnnotationTypes() { } @Override public SourceVersion getSupportedSourceVersion() { }

}

http://hannesdorfmann.com/annotation-processing/annotationprocessing101/

Page 36: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

How?public class MyProcessor extends AbstractProcessor {

@Override public synchronized void init(ProcessingEnvironment env){ } @Override public boolean process(

Set<? extends TypeElement> annotations, RoundEnvironment env) { } @Override public Set<String> getSupportedAnnotationTypes() { } @Override public SourceVersion getSupportedSourceVersion() { }

}

http://hannesdorfmann.com/annotation-processing/annotationprocessing101/

Page 37: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

How?MyProcessor.jar - com - example - MyProcessor.class

- META-INF - services - javax.annotation.processing.Processor

com.example.MyProcessor com.foo.OtherProcessor net.blabla.SpecialProcessor

javax.annotation.processing.Processor

javac will run the process in separate JVM

Page 38: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Examplepublic class PizzaStore { public Meal order(String mealName) {

if ("Margherita".equals(mealName)) return new MargheritaPizza(); if ("Calzone".equals(mealName)) return new CalzonePizza(); if ("Tiramisu".equals(mealName)) return new Tiramisu();

throw new IllegalArgumentException("Unknown meal '" + mealName + "'"); } }

Page 39: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Examplepublic class PizzaStore {

private MealFactory factory = new MealFactory();

public Meal order(String mealName) { return factory.create(mealName); }

}

Page 40: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

@Target(ElementType.TYPE) @Retention(RetentionPolicy.CLASS) public @interface Factory { Class type(); String id(); }

@Factory( id = "Margherita", type = Meal.class ) public class MargheritaPizza implements Meal {

@Override public float getPrice() { return 6f; } }

Page 41: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

How?public class MyProcessor extends AbstractProcessor {

@Override public synchronized void init(ProcessingEnvironment env){ } @Override public boolean process(

Set<? extends TypeElement> annotations, RoundEnvironment env) { } @Override public Set<String> getSupportedAnnotationTypes() { } @Override public SourceVersion getSupportedSourceVersion() { }

}

Page 42: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

@Override public Set<String> getSupportedAnnotationTypes() { Set<String> annotataions = new LinkedHashSet<String>(); annotataions.add(Factory.class.getCanonicalName()); return annotataions; }

@Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latestSupported(); }

Page 43: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

@Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); typeUtils = processingEnv.getTypeUtils(); elementUtils = processingEnv.getElementUtils(); filer = processingEnv.getFiler(); messager = processingEnv.getMessager(); }

Page 44: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

package com.example; // PackageElement

public class Foo { // TypeElement

private int a; // VariableElement private Foo other; // VariableElement

public Foo () {} // ExecuteableElement

public void setA ( // ExecuteableElement int newA // TypeElement ) {} }

Page 45: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

@Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {

// Itearate over all @Factory annotated elements for (Element annotatedElement : env.getElementsAnnotatedWith(Factory.class)){ ... } }

Page 46: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

@Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {

// Itearate over all @Factory annotated elements for (Element annotatedElement : env.getElementsAnnotatedWith(Factory.class)){ if (annotatedElement.getKind() != ElementKind.CLASS) { messager.printMessage(Diagnostic.Kind.ERROR, “Ooops!”, annotatedElement); return true; } ... } }

Page 47: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

public class FactoryAnnotatedClass {

private TypeElement annotatedClassElement;; private String simpleTypeName; // Class name private String id; // “Margherita”

public FactoryAnnotatedClass(TypeElement classElement) throws Exception { Factory annotation = classElement.getAnnotation(Factory.class); … } }

Page 48: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

try { Class<?> clazz = annotation.type(); qualifiedGroupClassName = clazz.getCanonicalName(); simpleFactoryGroupName = clazz.getSimpleName(); } catch (MirroredTypeException mte) { DeclaredType classTypeMirror = (DeclaredType) mte.getTypeMirror(); TypeElement classTypeElement = (TypeElement) classTypeMirror.asElement(); qualifiedGroupClassName = classTypeElement.getQualifiedName().toString(); simpleFactoryGroupName = classTypeElement.getSimpleName().toString(); }

Page 49: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

public void generateCode(Elements elementUtils, Filer filer) throws IOException { MethodSpec.Builder method = MethodSpec.methodBuilder("create") .addModifiers(Modifier.PUBLIC) .addParameter(String.class, "id") .returns(TypeName.get(superClassName.asType()));

// Foreach method.beginControlFlow("if ($S.equals(id))", item.getId()) .addStatement("return new $L()”, item.getTypeElement().getQualifiedName().toString()) .endControlFlow();

TypeSpec typeSpec = TypeSpec.classBuilder(factoryClassName) .addMethod(method.build()).build();

JavaFile.builder(packageName, typeSpec).build().writeTo(filer); }

https://github.com/square/javapoet

Page 50: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Processing Rounds

Page 51: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Annotation Processing

A tool build in javac for scanning and processing annotations at compile time

Page 52: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Dependency Injection

Page 53: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Dagger 2The fastest Java DI Framework!

https://google.github.io/dagger/

Page 54: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

import javax.inject.Inject;

class CoffeeMaker { @Inject Heater heater; @Inject Pump pump; ... }

Dagger 2

Page 55: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

@Component(modules = DripCoffeeModule.class) interface CoffeeShop { CoffeeMaker maker(); }

@Moduleclass DripCoffeeModule { @Provides static Heater provideHeater() { return new ElectricHeater(); }

@Provides static Pump providePump(Thermosiphon pump) { return pump; } }

Page 56: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

import javax.inject.Inject;

class CoffeeMaker { @Inject Heater heater; @Inject Pump pump; ... }

Dagger 2

CoffeeShop coffeeShop = DaggerCoffeeShop.create();

Page 57: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Dagger 2

๏ Singletons and Scoped Bindings ๏ Lazy injections ๏ Provider injections ๏ Qualifiers

Page 58: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Dagger 2The fastest Java DI Framework!

https://google.github.io/dagger/

Page 59: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

MapStructBean Mapping at Compile Time

http://mapstruct.org/

Page 60: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

public class Car { private String make; private int numberOfSeats; private CarType type; //constructor, getters, setters etc. }

Page 61: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

@Mapperpublic interface CarMapper { CarMapper INSTANCE = Mappers.getMapper( CarMapper.class ); @Mappings({ @Mapping(source = "make", target = "manufacturer"), @Mapping(source = "numberOfSeats", target = "seatCount") }) CarDto carToCarDto(Car car); }

Page 62: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

@Mapperpublic interface CarMapper { CarMapper INSTANCE = Mappers.getMapper( CarMapper.class ); @Mappings({ @Mapping(source = "make", target = "manufacturer"), @Mapping(source = "numberOfSeats", target = "seatCount") }) CarDto carToCarDto(Car car); }

Page 63: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

@Mapperpublic interface CarMapper { CarMapper INSTANCE = Mappers.getMapper( CarMapper.class ); @Mappings({ @Mapping(source = "make", target = "manufacturer"), @Mapping(source = "numberOfSeats", target = "seatCount") }) CarDto carToCarDto(Car car); }

Page 64: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

MapStruct

http://mapstruct.org/

๏ Nested mappings ๏ Updating existing bean instances

Page 65: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

RetrofitA type-safe HTTP client for Java

https://square.github.io/retrofit/

Page 66: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Retrofit

public interface WeatherData {

@GET(“weather?”) Observable<WeatherData> getWeatherData(@Query(“q”) String city);

}

Page 67: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Retrofit retrofit = new Retrofit.Builder() .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .baseUrl("http://api.openweathermap.org/data/2.5/") .build();

WeatherService weatherService = retrofit.create(WeatherService.class); Observable<WeatherData> london = weatherService.getWeatherData("Riga");

Page 68: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Retrofit

๏ Header Manipulation ๏ Sync and Asyn calls ๏ Custom Converters

Page 69: Marvel of Annotation Preprocessing in Java by Alexey Buzdin
Page 70: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

LombokSpice up your Java

https://projectlombok.org/

Page 71: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

@ToString@ToString(exclude="id")public class ToStringExample { private static final int STATIC_VAR = 10; private String name; private Shape shape = new Square(5, 10); private String[] tags; private int id; }

Page 72: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

@EqualsAndHashCode@EqualsAndHashCode(exclude={"id", "shape"}) public class EqualsAndHashCodeExample { private transient int transientVar = 10; private String name; private double score; private Shape shape = new Square(5, 10); private String[] tags; private int id; }

Page 73: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

@RequiredArgsConstructor@RequiredArgsConstructor(staticName = "of")@AllArgsConstructor(access = AccessLevel.PROTECTED)public class ConstructorExample<T> { private int x, y; @NonNull private T description; @NoArgsConstructor public static class NoArgsExample { @NonNull private String field; }}

Page 74: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

@Data & @Value@Data public class PoJo { private String name; private double score; private String[] tags; private int id; }

@Value public class PoJo { private String name; private double score; private String[] tags; private int id; }

Page 75: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

public String example() { val example = new ArrayList<String>(); example.add("Hello, World!"); val foo = example.get(0); return foo.toLowerCase();}

Page 76: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

public String example() { val example = new ArrayList<String>(); example.add("Hello, World!"); val foo = example.get(0); return foo.toLowerCase();}

val !!11one

Page 77: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

@ExtensionMethodclass Extensions { public static String toTitleCase(String in) { if (in.isEmpty()) return in; return "" + Character.toTitleCase(in.charAt(0)) + in.substring(1).toLowerCase(); } }

@ExtensionMethod({java.util.Arrays.class, Extensions.class}) public class ExtensionMethodExample { public String test() { return "hELlO, WORlD!”.toTitleCase(); } }

Page 78: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

lombok.fieldDefaults.defaultPrivate = true

Lombok.config

Page 79: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

LombokSpice up your Java

https://projectlombok.org/

๏@Builder ๏@Log ๏@Delegate

Page 80: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

• https://github.com/bluelinelabs/LoganSquare • https://github.com/greenrobot/EventBus • … and more

Page 81: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

ConclusionAnnotation Processing

Page 82: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Conclusion

Powerful Fast

Sometimes Brittle

Annotation Processing

Page 83: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Conclusion

Powerful Fast

Sometimes Brittle

Annotation Processing

Page 84: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Conclusion

Powerful Fast

Sometimes Brittle

Annotation Processing

Page 85: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Powerful Fast

Sometimes a Life Saver

Conclusion

Powerful Fast

Sometimes Brittle

Annotation Processing

Page 86: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

“Use it wisely we must!”

Page 87: Marvel of Annotation Preprocessing in Java by Alexey Buzdin

Q&AThank You!

@AlexeyBuzdinFollow me at