Freitag, 28. November 2014

Xtend - Active Annotations : Localization

Last time we took our first steps at implementing Xtend Annotation Processors. We did some simple modifications to the Java AST. This time we want to automate a much more involving pattern: Localization and ResourceBundles.

In Java you usually use .properties files to supply localized Strings for the UI. The ResourceBundle API allows you to access them in an untyped way using String constants. If you want more convenience, you need a static facade like this:


Writing this by hand gets tedious quickly, so many IDEs come with a wizard that generates this code for you. But you still need to manually trigger the generator and check that code into version control. Wouldn't it be cool if this statically typed facade was automatically generated and updated based on the property file?

That's exactly what the @Messages annotation does. The full source code is available on Github. There are many parts that you will easily understand with your knowledge from the previous post. For instance, the annotation adds a field to hold the ResourceBundle, a constructor that takes a Locale etc. The interesting part is where we actually read in the property file at compile time:


We use the Path API to find the physical location of the current class and get the property file of the same name. We give the user a good error message when we cannot find the file and just stop processing in that case.

Then we iterate over all messages in that property file and create a method for each. The name is converted from underscore to camelcase naming convention. For each pattern variable we create a method argument. By looking at the type of the pattern variables, we can also make some deductions about the type of the method arguments. For instance, if a pattern uses a NumberFormat, then only Numbers can possibly be passed to it. Again, we use Xtend's awesome template expressions to generate the body of the method.


With this in place, we now just add the @Messages annotation to an otherwise empty class that has the same name as our property file. All the static facade is automatically generated and available in content assist, outline, validation etc. You can even use existing Java tools like UCDetector to find messages that are no longer used. And every time you edit the property file later on, the Java code will be regenerated automatically!

There are many other untyped files that can benefit from a static facade to Java. Sven Efftinge wrote the @Jsonized annotation that takes some example JSON input and generates a Java class hierarchy from that. Toby Kurien maintains the Xtendroid project that parses the Android UI descriptor and automatically generates accessors for each UI element. Anton Kosyakov automated the creation of GWT ClientBundles and CSSResources.

What pattern would you automate? Try it out and tell your story in the forum =)

Dienstag, 25. November 2014

Xtend - Active Annotations Part 2

In the last part of the series we had a look at Xtend's built-in Active Annotations. This time you will learn how to write your own Active Annotations to get rid of boilerplate code.

Active Annotations are simply annotations marked with @Active and have an associated processor class. The processor gets access to the annotated elements (classes, methods, etc.) during different phases of the Xtend to Java compilation.

The corresponding interfaces are
  • RegisterGlobalsParticipant (announces additional types)
  • TransformationParticipant (changes the Java model)
  • ValidationParticipant (called after all transformations are done, but before code is generated)
  • CodeGenerationParticipant (generates additional non-Java code, like XML files etc.)
There are convenience base classes like AbstractMethodProcessor and AbstractClassProcessor that implement all these interfaces.

Let's start with the simple example of adding a logger field to a class. I've seen many people either have a template proposal in the IDE or copy-paste something like this over and over again:


We want to automate this, so we create an Active Annotation and extend AbstractClassProcessor.


As you can see, we get access to the Java AST model as well as lots of helpful methods from the TransformationContext object. Using these, we add the log field to the class and just give it some Java snippet as an initializer. We use a template variable when we want to refer to classes in the generated code. This way, imports are automatically organized for us.

Now we can just reuse our @Log annotation everywhere and never have to write the line of boilerplate again. Notice that you cannot use Active Annotations in the same project where they are defined. So put them in a dedicated project that you add as a library to your other projects.


Just as with the built-in annotations you will notice that the outline, validation, content assist etc. are aware of your new log field. Thanks to the primarySourceElement definition in our processor, navigation works correctly and goes to the class when the log field is selected. You can also take a look at the generated Java code to make sure it matches your expectations. It is automatically updated when you change something in the processor. This very useful when prototyping your own annotations.

In the upcoming posts we will build advanced processors and explore the Active Annotation API more thoroughly in the process. If you want to try some examples on your own, you can use New => Examples => Xtend Active Annotation Examples in Eclipse. Or you can have a look at some of my projects, like xtend-contrib and xtend-junit.

Dienstag, 18. November 2014

XRobots at Devoxx

Last week my colleague Miro and I were at Devoxx in Antwerp, joined by our trusty XRobots. This was the second conference that we brought our new game to and it was great fun again. Attendees could program their own robots and let them fight each other in a sumo-wrestling contest. The goal was to push the other one out of the arena or throw him off his feet. Some people spent their whole evening coming together for a robot hackathon at the Eclipse booth.


The robots are programmed with an Xtext based DSL. It uses the Xbase expression language and links against a Java API. It is then interpreted on the game server. The server sends movement commands to the LEGO Mindstorm robots and returns the robot position and orientation back to the user. Amazingly, you don't even need an IDE for that. The editor with syntax highlighting, validation and auto completion is available online, in your browser. You can give it a try at xrobots.itemis.de

If you want a real fight, the robots will be back to Belgium for EHACKB in early december. Miro will also give a talk on all the nitty-gritty implementation details. The next stop of our robot's world domination tour will be EclipseCon 2015 in San Francisco.

Web based editing is one of our main focuses for the future. We want to bring DSLs to end users without making them install heavyweight developer tools. There were already lots of interesting use cases that people told us about at the conference. We will be thrilled to enable them and making it all free and open source! Stay tuned for news on our website or contact us directly if you can't wait to get your web editing started.


I'd like to thank the organizers for their great work, everything went so smoothly. Also I want to give a shout-out to Jelena Alter for taking such good care of us. And most importantly thanks to you, the attendees who talked to us about Xtext and Xtend, for all the great feedback you provided. It was a pleasure and I hope to see you again next year!

Sonntag, 2. November 2014

Xtend - Active Annotations Part 1

There are many patterns in Java-land that make you feel like a robot. You write Accessors, Delegates, ValueObjects, ViewModels, XML bindings and many others. There is no real logic in this kind of code. You usually just copy-paste it or have your IDE auto-insert it. But all that boilerplate is still there and distracts the eye from the real logic of your program. And it is also easy to overlook a simple copy-paste error.

This is where Active Annotations come into play. They allow you to participate in the translation from Xtend to Java code. You can do everything from adding simple methods to creating completely new classes or generating arbitrary resources. And the IDE knows what you are doing at all times, giving you the navigation, validation and auto completion that your are used to with hand-written code.

The Xtend library ships with a few Active Annotations out of the box. Let's have a look at these first to get a basic idea of what they are all about.

@Data


Remember our Complex number example? We wanted an immutable datatype with two double values. Now normally we would have to write a constructor, getters, equals/hashCode and toString for that.


But there is an annotation that does exactly that. Just annotate the class with @Data and all the boilerplate is generated for you. Now you can focus on the interesting math. Neat, huh? ;)



When you switch the outline view into "JVM mode" you will also see all the generated members in grey. You can click on getters in the outline and are taken to the corresponding field and vice versa.


The generated methods and constructors are also proposed in content assist. The IDE experience is the same as if you had written them yourself. If you are curious, you can open up the generated Java file to assure yourself that the annotation does exactly what you expect.

@Accessors


Another common pattern are getters and setters. When you annotated a field with @Accessors, a getter and setter will be generated for you. If you put the annotation on a class, there will be getters and setters for all fields. If there are final fields, then there will be no setter for them of course. Instead there will be a constructor that takes those final fields.


Want to have getters only? Or protected setters? Or exclude one field completely? No problem, just use the AccessorType value inside the @Accessors annotation.


@Delegate


Quite often you want to implement an interface, reusing 95% of an existing implementation and only changing a few methods. That's exactly what @Delegate allows you to do. Just annotate a field or method with @Delegate.


Any interfaces that your class and the delegate object share will get default implementations that just forward the call to the delegate object. You can restrict the interfaces you want to have implemented by listing them inside the annotation.

@FinalFieldsConstructor, @EqualsHashCode, @ToString


These are basically the parts that make up @Data. We broke them out for two reasons. First of all because they are useful on their own. Secondly because you can use them to customize the behavior of @Data.

Let's say you don't like the default toString method and want a more concise representation. Just add @ToString(hideFieldNames = true, singleLine = true)

Or maybe your final-fields-constructor needs some additional annotations. Just write an empty constructor and annotate it with @FinalFieldsConstructor. The annotation will insert the boring parameters and body for you.



These annotations alone are a good reason to like Xtend. But the real killer feature is that you can easily write your own. Get ready to automate the hell out of your projects! =)