Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

"Xapi-lang For declarative code generation" By James Nelson


Published on

"Xapi-lang For declarative code generation"
By James Nelson
#GWTcon2017 Florence September 28-29th 2017

Published in: Technology
  • Be the first to comment

  • Be the first to like this

"Xapi-lang For declarative code generation" By James Nelson

  1. 1. Xapi-lang For Declarative Code Generation James Nelson (
  2. 2. Game Plan ● Why I (still) choose GWT ● Code generation, deferred binding & J2CL ● What is Xapi? ● What is Xapi-lang? ● What can I do with Xapi-lang? ● Code generation Best Practices ● Gwt 3 and beyond ● Shameless plug ● Q & A ● Save the world and get rich doing it :-)
  3. 3. Why I chose GWT ● The state of the web in 2007 ● Javascript sucked ● IE6 sucked ● Code generators! ● Transpilers! ● Optimizing Compilation! ● Type safety! ● Java Tools!
  4. 4. Why I still choose GWT ● Plays nicely with Javascript ● Plays nicely with Android and IOS * ● Code generators! ● Transpilers! ● Optimizing Compilation! ● Type safety! ● Java Tools! ● Mature, well tested framework * Java can target web, mobile, desktop and server
  5. 5. Codegen, Deferred Binding & J2CL ● Code generation, like alcohol, is good in moderation (Alex Lowe) ● GWT is the first (only?) web framework with compile- time code generation ● Automate away boilerplate ● More declarative, less typos ● Express intent with annotations and interfaces ● Why do at runtime what you can do at compile time? ● Going away in J2CL :-(
  6. 6. Codegen, Deferred Binding & J2CL ● Why is it called deferred binding? – In the expression level “JJS AST”, GWT.create() calls are converted to nodes which contain an expression for each permutation, to be distilled into distinct permutations (unless you have collapsed permutations) ● Enables you to inject “magic” at compile time – While purists prefer to avoid magic, sometimes the best practical solution is to hide your complexity in the compiler instead of polluting your runtime or requiring repetitive copy-pasta “solutions”. ● Major selling point in the days of extreme browser fragmentation ● Going away in J2CL :-(
  7. 7. Codegen, Deferred Binding & J2CL ● J2CL only handles translating .java into .java.js ● Any and all code generation, browser quirks or magic must exist outside of the J2CL compiler ● Any and all solutions that work for J2CL will also work for GWT 2.X ● Contrary to some popular philosophy, I believe we need more and better magic in our toolchain ● For existing applications to upgrade to GWT 3, we need working solutions for the magic we depend on – It is far easier to say “just don’t do it” than it is to undo “it”
  8. 8. What is Xapi? ● Stands for “Extremely Extensible Cross Platform API” ● Acts like deferred binding for the entire java ecosystem ● Highly modularized “kitchen sink” of tools ● Services that run in Gwt, Javafx, servers and Android (IOS support when time is found for J2ObjC) ● Contains a vast array of code generation and build tools ● Uses a custom fork of GWT that has support for java reflection and “magic method injection” – GWT.create() is the only “stock” magic method – Xapi lets you define your own magic methods ● WARNING: The current version is a prototype!
  9. 9. What is Xapi-lang? ● Java parser enhanced with new expression structure – Forked from ● <xml-like syntax=supported() /> ● { json-like: syntax(), supported: [ true ] } ● .css-like { syntax: supported(); } ● `template strings? Oh ya, supported too!` ● Any expression can contain valid java, but java can only contain `template strings`
  10. 10. Xapi-lang: Under the hood ● Xapi-lang is not executable (no interpreter) ● Parses your document into an Abstract Syntax Tree, representing the structure of your code ● You apply various visitors to analyze the AST, and produce meaningful output ● Can be used for templating, code generation, or creating a “Domain Specific Dialect” – While the language itself allows you to mix and match xml, json, css and java, your AST consumer can permit only specific structures (like various xml tag names or attributes that are only allowed in certain tags).
  11. 11. Xapi-lang Use Case: Class Templating // you can supply replacements for any $name package $myPackage; import the.good.Stuff; public class $MyClass implements Stuff { public void doStuff(@NonNull String s) { // you can also create “magic methods”, // which are called, with parsed arguments, at build time // and can return one or more expressions to add to the source System.out.println($compilerMagicGoesHere(s)); } }
  12. 12. Xapi-lang Use Case: Class Templating Expression $compilerMagicGoesHere(Expression argument) { boolean notNull = argument.hasAnnotation(“NotNull”); if (notNull) { return new BinaryExpr(argument, StringLiteralExpr.of(“ is not null”),; } else { return new ConditionalExpr( new BinaryExpr(argument, NullLiteralExpr.NULL, Operator.equals), StringLiteralExpr.of(“argument is null”), new BinaryExpr(argument, StringLiteralExpr.of(“ is not null”), ); } } new ApiGenerator(“MyTemplate.xapi”) .generateWith(“myPackage”, “”, “MyClass”, “Classname”);
  13. 13. Xapi-lang Use Case: Class Templating // you can supply replacements for any $name package; import the.good.Stuff; public class Classname implements Stuff { public void doStuff(@NonNull String s) { // you can also create “magic methods”, // which are called, with parsed arguments, at build time // and can return one or more expressions to add to the source System.out.println(s + “ is not null”); } }
  14. 14. Xapi-lang Use Case: API Generator <generateInterface var = { size : 5, typeParams : $range(1, $size, $i->`In$i`), } template = public interface Function$size <$typeParams, Out> { @unfold(from = 1, to = $size, var = i) Out apply(In$i ... in$i); @unfold(from = 1, to = $size, var = i) @var( name = mapParams, value = $range(1, $size, $p -> $p == $i ? To : `In$p`) ) @var( name = lambdaParams, value = $range(1, $size, $p -> in$p ) ) default <To> Function$size<$mapParams, Out> map$i(Function1<In$i, To> mapper){ return ( $lambdaParams ) -> apply( range(1, $size, $a -> $a == $n ? mapper.apply(in$a) : in$a ) ); } } />
  15. 15. Xapi-lang Use Case: API Generator public interface Function1<In1, Out> { Out apply(In1 in1); default <To> Function1<To, Out> map1(Function1<In1, To> mapper){ return ( in1 ) -> apply( mapper.apply(in1) ) ); } } public interface Function2<In1, In2, Out> { Out apply(In1 in1, In2 in2); default <To> Function2<To, In2, Out> map1(Function1<In1, To> mapper){ return ( in1, in2 ) -> apply( mapper.apply(in1), in2 ) ); } default <To> Function2<In1, To, Out> map2(Function1<In2, To> mapper){ return ( in1, in2 ) -> apply( in1, mapper.apply(in2) ) ); } }
  16. 16. Xapi-lang Use Case: Ui Generation <define-tag name = “my-input” model = { value: String, placeholder: @Nullable String, label: @Nullable String, } ui = <box> <if notNull=$model::label whenTrue = <label>$model::label</label> /if> <native-element gwt=<input value=$model::value placeholder=$model::placeholder /input> javafx=<javafx.scene.text.Text … /> /native-element> </box> /define-tag>
  17. 17. Xapi-lang Use Case: Ui Generation public interface MyInputModel extends Model { String getValue(); void setValue(String value); String getPlaceholder(); void setPlaceholder(String placeholder); String getLabel(); void setLabel(String label); } public abstract class MyInputBase <Element> extends IsModelComponent <Element, MyInputModel> { void render(DomBuffer dom) { DomBuffer box = dom.makeTag(“box”); MyInputModel model = getModel(); if ( model.getLabel() != null ) { box.makeTag(“label”) .append(model.getLabel()); } appendNativeElement0(box); } protected abstract void appendNativeElement0(DomBuffer dom); } public class MyInputGwt extends MyInputBase <elemental2.dom.Element> { protected void appendNativeElement0(DomBuffer dom) { MyInputModel model = getModel(); dom.makeTag(“input”) .setAttribute(“placeholder”, model.getPlaceholder()) .setAttribute(“value”, model.getValue()); } }
  18. 18. Xapi-lang Use Case: Ui Binding ● Not actually implemented, but certainly possible ● Use apt, asm, javassist, reflection or xapi to read @Ui annotations ● Visit xml using xapi to identify nodes to bind ● Generate html with a means to perform node replacement – Xapi has a PotentialNode class which lets you build html and add callbacks to elements that have not been created yet ● Performs code generation outside of Gwt toolchain – Less work during compile – Leverages incremental compilation – Actually readable for your debugging pleasure
  19. 19. Code Generation Best Practices ● Code generation, like alcohol, is best in moderation (Alex Lowe) ● Do not pound in nails with a sledgehammer ● Most problems that can be solved by code generation should not be solved by code generation (especially when you are on the clock!) – Dynamic, repetitive or very complex code is better to generate ● If you are generating any methods that are not dynamic, you should probably refactor them out of your generator ● When generating code, the last thing to write is the generator – Start by writing your input template (unless your generator is reading artifacts produced elsewhere) – Next, write at least three implementations by hand – Then, write tests for your manual implementations – Finally, write a generator to produce the output that passes tests
  20. 20. GWT 3 and Beyond ● Before we can even think of releasing GWT 3, we need to rebuild the GWT toolchain on top of J2CL ● Code generators, linkers and deferred binding support most of the (good) stuff in gwt-user. ● We, the community, must rebuild these tools using standard java tooling, and then apply J2CL at the end of our build ● Xapi has prototypes of many tools we will need to do this job – Apt / Javac compiler plugins – Code generators tools – Xapi-lang – “Deferred binding for Java” (X_Inject) – Both Gwtc and Javac compiler services (much easier to debug compilers from IDE when you don’t need remote process debugging) – Useful abstractions to build opinionated implementations that downstream users can replace with their own version if they don’t like ours
  21. 21. Shameless Plug ● Colin Alworth, Justin Hickman and myself are launching a new company called Vertispan ● We are selling support contracts for the Gwt ecosystem (you can buy N hours per month for us to help you fix your problems) ● We are selling consulting services to write code for you (yes, we do charge more to work on your proprietary codebase) ● We are going to support GWT 2.X and migration to GWT 3 ● If you have a bug in GWT itself, you now have the option to pay to get it fixed (we want to fix everything, but time is limited!) – In most cases, all fixes will be shared with the community – If you need a crazy hack and are willing to accept that responsibility, we will push jars to a private repo for you ● When we find the time, we also want to build a new GWT framework – Colin and Justin have both been lead GXT developers
  22. 22. Q & A Ask me anything Come chat @ Tell your friends!
  23. 23. Save The World, And Get Rich Doing It ● You thought I was joking, didn’t you? ● Xapi is not just a fun project for evenings and weekends ● We The Internet, the other company on my cover slide, is a project to build tools to fix our political system – Currently a private prototype that still isn’t ready for public – Includes a structured markup language for developing complex ideas that can still be presented concisely – Will use a git-like model for users to collaborate on ideas – Will include tools for voting and debating on ideas – Will include tools to draft and vote on laws – The final form is meant to be an implementation of distributed, real-time direct democracy (spread power too thin to be abused) ● The project, once launched, will distribute most of its profits to users – People with great ideas to fix the world should get paid to work on it – Everyone else can support those leaders by using the site – Will use in-app purchases, but must be “Free to Win” (not “Pay to Win”) ● If you want to be a beta tester, please email