Dynamic Languages: Rationalizations and Myths

61 Comments

The Patriots loss in the Superbowl has gotten me so depressed and down that I need to take it out on somebody. I need to rant about something, so why not about some things that have annoyed me over the past few months about the dynmaic language community.

I recently emailed the mandelbrot benchmark to a dynamic language evangelist colleague. Although benchmark results are usually pure propaganda, poor representations of how a language or framework is used in the real world, or even just plainly out of date with the latest versions of the technology, still, the performance of dynamic languages compared to Java in the example is quite embarrassing. Ruby, for example, is 500 times slower! Yeah, its hard to take seriously a benchmark that outputs to stdout, but still, if you look at the code you’re thinking, WTF is Ruby doing that causes so much overhead?

Now, when I forwarded this benchmark to my evangelist colleague, he immediately accused me of trying to put down or stamp out any challenge to the “One True Language” (Java). Its not about putting down or stamping out. Its about testing whether or not a language is a viable application platform. The thing is, if the dynamic language crowd is going to position itself as a replacement for Java in application development then they are going to have stop giving silly rationalizations for their shortcomings and promoting myths about their language and Java. This, and this alone is what irritates me about this crowd. Let me give you some examples about the rationalizations and myths they try to pull over on us:

RATIONALIZATIONS

Dynamic Language XXXX didn’t do well against Java in XXXX benchmark

Rationalization: “Benchmarks indicate very little practical information about the overall utility and performance of a given language or runtime.”

Reality: Although benchmarks are either propaganda, out-dated, or not a good representation of real-world usages, glaring differences must be recognized. A 5%, 10%, or even 100-200% difference is probably as a result of tuning or some simple undiscovered bug. In the grand scheme of things, those kind of numbers ain’t very relevant. But a 50000% difference? For such a simple benchmark? Something is seriously wrong here.

This reminds of 2002, when I first ran JBoss against the J2EE SpecJ benchmark. We had some pretty embarrassing numbers at first way back then. Although SpecJ is clearly a silly, non-real-world benchmark, it allowed us to identify many major and minor bottlenecks and helped our project to mature. For some dynamic languages like Ruby, I think what the mandelbrot benchmark showed was that the VMs/implementations of dynamic languages like Ruby are still very immature compared to Java. I don’t believe that it shows anything seriously wrong with the language syntax of these dynamic languages themselves though. Java received similar attacks in the mid 90s when it came out. Since then, the JVM has improved dramatically and according to the mandelbrot benchmark, only 10% slower than C. I expect the same out of the Ruby guys eventually. I’ll have to see how this benchmark improves under JRuby.

Ruby VM cannot support kernel threads

Rationalization: “Green threads are good enough.” OR: “Who cares, I can just run multiple processes.”

Reality: Even the basic laptop nowadays has parallel computing power. Green threads don’t take advantage of this. Blocking I/O also creates huge problems with Green Threads. Solving the problem by running many processes is a poor solution. A process is just too heavy weight compared to a thread which is why we have threads in the first place. It is very common for server-side Java applications to service hundreds of concurrent users. Besides, running multiple single-threaded processes starts to negate some of the benefits of simple design patterns like caching.

If dynamic languages like Ruby want to position themselves as a viable alternative to Java for an application platform, they are going to have to solve these issues. Many will say, “Its probably good enough for simple apps”, but it is not uncommon for project leaders to underestimate how much traffic they will get, or how much they have to scale.

Dynamic languages like Ruby, Python, etc… are not typesafe/statically typed

Rationalization: “Type-safety makes my code too verbose and makes me less productive.”

Reality: Why can’t these people learn how to type? Modern IDEs make this point totally moot with code completion and code generation. Besides, why can’t we have a dynamic statically typed language?

Lack of type safety doesn’t scale well to large teams

Rationalization: Anybody noticing the “Any software written by a large team will ultimately fail.” articles floating around in the community? Am I paranoid, or is this yet another attempt at brainwashing us into believing dynamic languages are the next fad in software development?

Reality: There are a lot of large applications in the industry being written. This reminds me of a story my colleague Jason Greene told me. He was working on a very large python project. Lack of static typing ending up being such a coordination and maintenance problem they ended up having a coding policy where everybody had to embed type information into the variable names of method parameters. Funny, eh?

Lack of static typing does not allow for reliable refactoring in modern IDEs

Rationalization: “The productivity of dynamic language XXXX makes refactoring irrelevant. Anyways, there are IDEs for Ruby out there that support refactoring”. OR, my favorite: “I don’t use an IDE, what do I care?”

Reality: I was a VI/Emacs user up until 2002 when Intellij came out with refactoring capabilities. Up until then, I was as productive with emacs, find, grep, and sed as I could be with any IDE out there. After finally becoming familiar with Intellij and its refactoring capabilities, I found that I was 5, 10 times more productive with my IDE than I was before. Now, Ruby fanboys will argue, “Intellij and Netbeans have refactoring capabilities for Ruby!” My answer is, it is not reliable refactoring. Take this example Cedric Beust gave on a recent TSS thread:

def f1(o)
  o.init
end   

def f2(o)
  o.init
end   

class C
  def init
    ...
  end
end    

class D
   def init
     ...
   end
end

If you rename C.init to C.init2, how can the IDE know which o.init must be renamed in f1 and f2? The IDE could either do these refactorings automatically (dangerous) or prompt you to confirm at each replacement point (tedious). In either case, any productivity you’ve gained with the elegance of Ruby is lost 10 times over.

So, these are just some of the rationalizations the dynamic language crowd gives when confronted with criticism. Now let’s talk about some of the myths and propaganda that is being fostered.

MYTHS

Software Engineers should use the best language for the job

Reality: I don’t know about the rest of you, but throughout my career I’ve either been developing middleware or writing applications. What other job is there really out there? Or maybe they are saying, “XXX dynamic language is good enough to solve certain application requirements”? Good enough has never really been good enough for me.

Besides, its hard enough to find an expert in one language. Its a maintenance and integration nightmare to have a project written in multiple languages. This can be bridged, to a degree, with dynamic language implementations that run on the JVM: JRuby and Jython are good examples. But unless these implementations become mainstream, they can quickly become out of date, i.e. Jython.

More lines of code means more bugs, thus dynamic languages are better.

Reality: Modern IDEs fills this gap. TDD is viable in type-safe languages too! I’m probably doing my own rationalization here, yes… JBoss 5, for example, is the 3rd major refactoring of the JBoss Application Server that I’ve lived through. I just can’t imagine doing it without the reliable refactoring that modern Java IDEs provide.

I am more productive in XXX dynamic language because the syntax is cleaner, more elegant, and more powerful.

Reality: Because Modern IDEs with a statically typed language can do reliable refactoring, this productivity gain has diminishing returns as your project gets larger. Even with small, one man projects, this reliable refactoring offsets any productivity gain you get with the dynamic language. At least, that’s what I’ve experienced.

I’ve done a decent sized project in Python before. I did find I was more productive with the first implementation. The problem is, I’m not a very clean programmer, so I end up iterating and refactoring constantly. In my case, a powerful IDE has made me incredibly more productive. Something I just could not get with a dynamic language.

Am I just a Java fanboy?

Maybe, but I don’t think so. Throughout my career I’ve done projects in Pascal, assembly, C, C++, Fortran, Tcl, Perl, Python, Visual Basic, Java, and even hacked around a little bit with PHP. While I don’t believe that Java is the one langauge to RULE THEM ALL, I do believe it is vastly superior to anything out there to build applications with. I also do not believe that Java is the end all, be all of existence. It still needs elegant, typesafe closures to complement annotations as a way to implement DSL. It needs a standard, non-code generating way of adding behavior to annotations. It needs a structural syntax to make initialization easier. AOP support might be nice too, or at least JVM support to make it easier to implement AOP-like features. Better zero-turnaround development features in both the JVM and APIs like Java EE, Seam, Hibernate, Spring, and JBoss AS would help out tremendously as well. Really, I’d be fine to dump Java for a language that supports all these things but the new language must:

  • Be typesafe, statically typed
  • Have an IDE that supports the same features as modern Java IDEs
  • Have a rich set apis and libraries to build my applications from
  • Have a viable commercial ecosystem
  • Have a vibrant open source community

While current dynamic languages do have some of these attributes, none contain all, so until then Java is my choice and I will remain a boy who is a Java fan.

Finally, I hope you realize that I’m not trying to stamp out dynamic languages, but rather hoping, in vain, that the dynamic language community admits their faults. I do wish that a statically typed dynamic language would come of age, but until then, I’ll stick with Java. Really, I don’t know why somebody hasn’t done it it. Is static typing really that hard to implement well? For example, why not gut Groovy and have Dynamic Java? Or do the same with Scala? Or add static typing to Python and get Jython up-to-date?

Well thats it, expect more ranting in the next few weeks/months on a variety of subjects. Its gonna take a long long time to get the Pats loss out of my system….

Edited: 2/22/08

Many people have been confused on what I meant by statically typed dynamic language.

1) Typesafe introductions/mixins to either an instance or a class

For example:

class Foo {}
class Mixin implements MixinInterface {}
Mixin.add(Foo.class, new Mixin(), MixinInterface.class);
Foo foo = new Foo();
 MixinInterface intf = (MixinInterface)foo;

Or:

Foo foo = new Foo();
Foo bar = new Foo();
Mixin.add(foo, new Mixin(), MixinInterface.class);
(foo instanceof MixinInterface) == true
(bar instanceof MixinInterface) == false

2) Ability to do AOP things like field/method/constructor interception without having to do bytecode magic
3) Ability to plug in at runtime annotation processing (not the Javac crap).
4) An instrument library that allows you to make schema changes to classes. (didn’t state this before)


Improvements to Scannotation

1 Comment

I made a few little improvements to Scannotation that I needed to have in our JSR-311 implementation:

  • CrossRefException is now a checked exception. You should be forced to deal with this exception.
  • Configurable ignored packages. You can specify which packages you do not want to scan. Performance tweak.
  • Meta-annotations are now cross-referenceable if you invoke the appropriate APIs. What do I mean by this?

Example of cross-referencing meta-annotations:

@HttpMethod("GET")
public @interface GET {}

public class BookStore {
    @GET String getBook() {...}
}

BookStore can now be cross-referenced with @HttpMethod if you call the appropriate method on AnnotationDB.


			

Is JAX-RS (Restful Java) just another IDL?

3 Comments

I was reading a bit of Steve Vinoski’s blog on how some think REST requires a definition language like WSDL or IDL. He first mentions it within Serendipitous Reuse, and further expands on it in the blogs Lying Through Their Teeth: Easy vs. Simple, IDL vs. Human Documentation and More REST and IDL. If you are a REST fan or detractor these blogs as well as the blogs they link to are a good read and gets you thinking about things.

I’ve been implementing JAX-RS, JSR-311, off and on the past few months. Vinoski’s blogs made me think, is JSR-311 just another definition language? The language being Java + JAX-RS anotations? Maybe I’m dwelling over the obvious here, but let’s do the exercise anyways…

Vinoski paraphrases Ryan Tomayko on what might be the erroneous use of a RESTful definition language:

Among other things, Ryan touches on one of the favorite assertions of the REST detractors, which is that REST can’t be effective without an interface/service/resource definition language. After all, without such a language, how can you generate code, which in turn will ease the development of the distributed system by making it all look like a local system? Not surprisingly, the first comment on Ryan’s blog entry is exactly along these lines.

First of all, I don’t think JAX-RS is trying to make a distributed system look like a local one. Yes, its trying to remove a lot of boilerplate code. Yes, using JAX-RS could turn a POJO into a distributed RESTful resource.

public class BookStore {
    @GET @Path("/books/{id}")
    @ProduceMime("application/json")
    public String getBook(@PathParam("id") int id) {
         ... return a json representation of the Book
    }
}

JAX-RS does have some characteristics of a definition language. From the @GET and @Path annotations, you can determine how the resource is going to be invoked on. But, IMO though, it is more of a mapping language than a definition language. Its mapping a URI and http request/response to the invocation of a Java method. Its not trying to make our distributed system look like a local system.

Now, what about the idea I had of providing a client framework using JAX-RS annotations?

public interface BookStore {
    @GET @Path("/books/{id}")
    @ProduceMime("application/json")
    public String getBook(@PathParam("id") int id);
}

The idea here would be you generate a RESTful client proxy from a JAX-RS annotated interface that you could invoke on without writing http client code. Are we blurring the lines here? Are we hiding too much the fact that our BookStore is a remote distributed service? I’ll leave that up to you to decide…

Scanning Java Annotations at Runtime

36 Comments

When writing an annotation-based framework, you many times have the need to find all classes that use a specific annotation at deployment time to initialize your framework. For example, the EJB 3.0 deployer needs to know which classes are annotated with @Stateless, @Stateful, and @MessageDriven, so it can create a container for each of those classes. For JPA, it needs to find a given set of classes within an archive that are annotated with @Entity so that it can define its ORM mapping. This scanning for annotations can be done at runtime using various techniques and open source libraries. I want to discuss how to do this in my blog and point you to a small project I created at sourceforge to help out with this.

Finding archives to scan

The first thing you need to do is to find actual archives you want to scan for classes. Depending on your environment there are different ways to accomplish this.

Java classpath

The “java.class.path” system property, if set properly (FYI, maven doesn’t set it properly), can be a way to obtain a list of classpath/archives you can scan for annotated classes. Although it it only provides relative paths, you can easily turn these into URLs and/or InputStreams for iterating over.

Using your classloader

Using ClassLoader.getResource() and ClassLoader.getResources() is a way to obtain URLs to specific resources in your classpath. From these specific resources you can extract the base url of the classpath/archive the resource resides in by chopping off the base resource name. For example, one common technique is to have a marker file in each of your archives. For JPA, this marker file is META-INF/persistence.xml. You could then to ClassLoader.getResources() to find all classpaths/archives that contain that file:

ClassLoader cl = Thread.currentThread().getContextClassLoader();
Enumeration<URL> urls = cl.getResources("META-INF/persistence.xml");

Calculating the URL of the classpath/archive is just a matter of a little string manipulation of the url.

Web Applications

In web applications its very easy to obtain URLs that point to jars within WEB-INF/lib or to extract where the WEB-INF/classes path is by using the ServletContext class. The class has a nice method getResourcePaths() that returns URLs to what you want. For example:

List<URL> urls = new ArrayList<URL>();

Set libJars = servletContext.getResourcePaths("/WEB-INF/lib");
for (Object jar : libJars)
{
    try
    {
       urls.add(servletContext.getResource((String) jar));
    }
    catch (MalformedURLException e)
    {
       throw new RuntimeException(e);
    }
}

ServletContext.getResourcePaths() returns a directory like list of all paths under the specified base path you provide as a parameter. Passing in “/WEB-INF/lib” will get you a listing of all .jar files within /WEB-INF/lib of your web application. Once you have this listing, you can do ServletContext.getResource() to obtain a URL pointing to each of the .jar files.

To find the /WEB-INF/classes is a little trickier.

URL classesPath = null;
Set libJars = servletContext.getResourcePaths("/WEB-INF/classes");
for (Object jar : libJars)
{
   try
   {
      URL url = servletContext.getResource((String) jar);
      String urlString = url.toString();
      int index = urlString.lastIndexOf("/WEB-INF/classes/");
      urlString = urlString.substring(0, index + "/WEB-INF/classes/".length());
      classesPath = new URL(urlString);       break;    }
   catch (MalformedURLException e)
   {
      throw new RuntimeException(e);
   }
}

You use the same ServletContext.getResourcePaths() and ServletContext.getResource() but you must do some string manipulation to the URL to get the base path. If you are deploying things within a web framework, you can write a ServletContextListener that obtains access to the servlet context.

Browsing archives

Once you have URLs pointing to directories or .jar files that make up your classpath (or the set of archives/paths you want to scan) you need to browse them. You can usually assume that URLs ending in “/” are some form of a directory while those not ending in “/” are .jar files. If you hack and step through URLClassLoader code, you’ll find that it makes the same assumption. Browsing jars is very easy. If you have a URL pointing to a .jar file all you need to do is open an InputStream to it and instantiate a JarInputStream. This class has methods that allow you to list and open files within the jar archive.

URLs that point to a directory poses an abstraction problem. Browsing a directory structure is protocol specific. If the URL protocol is “file:” you can just use java.io.File. If its “http:”, you need to use a WebDAV library. If its a different protocol, you need to find a library that allows you to browse that particular protocol.

Finding annotated classes

So, once you have access to your classpaths you can obtain a list of .class files within those classpaths. It generally is a very bad idea to load each and every one of those classes using your ClassLoader and use the Java reflection API to scan for annotations you are interested in.

  1. Use the Java reflection API only allows you to see annotations that are visible at runtime. If you remember your JDK 5.0 lessons, there are 3 types of annotation. Source, Class, and Runtime. Class and Runtime are compiled into your .class files, but only Runtime are visible at runtime.
  2. You generally do not use each and every class in the libraries you are scanning. If you load each class into your ClassLoader, you are filling up the JVM’s perm-gen space and wasting resources.

So, if you’re not going to load the class through your classloader, how do you scan for annotations? The answer is to use a bytecode processing library like Javassist or ASM. I am most familiar with Javassist since I wrote the annotation processing for it so let’s show examples using that library. ASM is perfectly good as well for this purpose.

With Javassist, you load up a ClassFile instance from the InputStreams you browse from your .jar or classpath. This object allows you to view the bytecode structure of your .class file without loading the class and find the string names of the annotations attached to each element of the class

DataInputStream dstream = new DataInputStream(new BufferedInputStream(bits));

ClassFile cf =  new ClassFile(dstream);
String className = cf.getName();
AnnotationsAttribute visible = (AnnotationsAttribute) cf.getAttribute(AnnotationsAttribute.visibleTag);
AnnotationsAttribute invisible = (AnnotationsAttribute) cf.getAttribute(AnnotationsAttribute.invisibleTag);
for (javassist.bytecode.Annotation ann : visible.getAnnotations())
{
     System.out.println("@" + ann.getTypeName());
}

The visible and invisible attributes correspond to Runtime and Class visible annotations. From this information you can obtain annotations attached to the class. Javassist has a reflection-like api that allows you to iterate over methods and fields of the ClassFile. Getting annotation information for methods and fields is exactly the same as getting them from the class.

New Scannotation Framework

I’m writing this blog because I actually had to do a lot of this scanning for JBoss’s EJB container and recently the JAX-RS implementation I’m working on. Because I thought this code might be useful, I created a sourceforge project for it called Scannotation. The Scannotation framework encapsulates all the ideas and functionality I talked about in this blog. It centers around three classes: ClasspathUrlFinder, WarUrlFinder, and AnnotationDB.

ClasspathUrlFinder finds classpath URLs for you. It has methods to obtain them from the java.class.path System property. Other methods to find an archive URL by providing a classloader resource name as described earlier in this blog. WarUrlFinder encapsulates finding URLs for your WEB-INF/classes directory as well as the jars in WEB-INF/lib. Its pointless to repeat the javadocs for these classes so just follow the links above to find out more information.

The AnnotationDB class consumes URLs you find through ClasspathUrlFinder or WarUrlFinder. It scans them for .class files and uses Javassist to make two indexes:

  • An index keyed on the fully qualified name of an annotation, with a set of classes that use that annotation
  • An index of fully qualified class names with a set of annotations that that particular class uses

Here’s an example of scanning your Classpath:

URL[] urls = ClasspathUrlFinder.findClassPaths(); // scan java.class.path
AnnotationDB db = new AnnotationDB(); db.scanArchives(urls);

Here’s another example of scanning all JPA archives:

URL[] urls = ClasspathUrlFinder.findResourceBases("META-INF/persistence.xml");
AnnotationDB db = new AnnotationDB();
db.scanArchives(urls);
Set<String> entityClasses = db.getAnnotationIndex().get(javax.persistence.Entity.class.getName());

From this mini annotation database, your annotation frameworks can pick out which classes the care about more easily. Eventually I want to write ant task and maven plugin that will add an annotation index into a file within META-INF of your jars. That way you could precompile this index at build time and save some CPU cycles. If anybody is interested in doing this, let me know and I’ll give you SVN access to the project.

EDITED 3/31/2009:

You might want to check out the Reflections project.  I think they have taken scannotations to the next level.  I personally have not been able to maintain the scannotations project.

Java Developer’s Day: Krakow, Poland

10 Comments

About two months ago I received an email from Andrej Targosz asking if I would like to present at Java Developer’s Day in Krakow, Poland. Being of Polish decent (yes, Burke is Irish, but my grandmother is a full blooded Pole), I really wanted to go just to see the country. The fact that I would be speaking in front of about 400 Polish Java developers was also a huge plus. Jonas Boner, a long time adversary in the AOP space was slated to give a talk. Me and him always had gotten along really well, and it would be good to seem him. The JBoss guys that run JBoss.org live in Warsaw and decided they’d come down. The lead of JBoss Business Activity Framework, Maciej Machulak another Pole, was also invited to talk about his project. Considering how I have blogged about his stuff recently, it would be really cool to meet him in person. Besides, when JBoss guys get together, it’s always a party no matter where in the world we’re from.

PROIDEA

First, I want to give kudos to PROIDEA, the organizers of the conference. Besides organizing a professional, well-run conference, they went above and beyond the call of duty and made my stay truly special. They picked me up at the airport and even though the conference was held outside of the city , they set me up at a nice apartment right in the city’s center. When Anna Kolodziejczyk, one of the conference’s key organizers, heard that other JBossians from Warsaw were coming, she scheduled and booked their train for them. She even gave up her weekend to show me and the other JBossians around Krakow. Andrej Targosz, the head of PROIDEA, got up at the early hour of 4:00 am to drive me to the airport Monday morning. Finally, I missed my daughter’s birthday to attend the conference. To make up for it they sent me home with a traditional Polish doll and a stuffed animal of the city’s mascot, the Krakow dragon.  I can’t thank Anna and Andrej enough for such a great trip.

Day One

I arrived on Thursday morning. After a nap, Andrej and Anna picked me up for dinner and to meet one of the sponsor’s of the conference, DRQ. Besides talking business, tech, and the general discussion that people from different countries always make, I was introduced to some tasty Polish food: their traditional Polish soup (Help me out guys! I can’t remember the name to save my life), and a sweet, hot, red and spicy wine(come on Poles, give me the name). I ended up ordering those two things any time I went out to dinner the whole trip. The DRQ guys made me feel special by giving me a gift of a painting of Krakow’s city center as well as a copy of my O’Reilly EJB 3.0 book translated into polish. I could not believe my book had been translated. They told me that the Polish publisher donated 40 copies of the Polish version of my book to the conference. Man, my 92 old grandmother is gonna freak when she sees it!

Day Two

The second day was the actual conference. I was first up and gave a talk, of course, about EJB 3.0 and covered both its integration with JPA and how to use EJB 3.0 interceptors. I didn’t get to see the 2nd by DRQ’s, Artur Basiura, because PROIDEA was having some online magazine (I don’t remember their name) do video interviews of each presenter. Jonas Boner gave a nice talk on Terracotta’s product. He always gives a great presentation and it was interesting to see how Terracotta stacked up with JBoss Cache and JBoss POJO Cache. I didn’t get to see Dariusz Zbik, of Software Mind’s presentation as PROIDEA wanted me to sign the 40 copies of my book they were giving away. It would have been difficult anyways as I believe his presentation was entirely in Polish.

In the afternoon I had a one-on-one meeting with some of the developers of DRQ, one of the conference’s sponsor. The meeting lasted a few hours in which DRQ drilled me for information about JBoss, open source, and the general state of Java. You can pretty much gauge the talent of a developer by the quality of questions they throw at you. From that I could tell, DRQ had some pretty good engineers. Being a JBoss user, it was also cool to learn what pieces of JBoss they were using to solve their customer needs.

After meeting with DRQ I rushed to see Maciej’s presentation on JBoss Business Activity Framework. Being lazy, I had only looked at the basic examples of his project and didn’t dive down into the gory details. His presentation filled in the gaps for me. One cool thing I learned was that his framework turns every transactional event into a callback. A bunch of ideas are brewing in my head around this that I hope to blog about later.

Lastly, I was able to see the last presenter of the day, Jacek Laskowski, give a presentation in Polish about Geronimo 2. He was probably the most energetic presenter of the conference. One funny thing he did was that he was wearing 5 different t-shirts. Whenever he changed subject, he changed the t-shirt he was wearing which had the audience roaring in laughter. He had the audience pretty captivated. I will give him one critism though. He talked way too much about us. I counted about 30-35 times he said the word JBoss. Why are Geronimo contributors so obsessed with us? If you’re giving a talk, yeah, maybe you might want to mention who your competitors are, but if you talk about your main competitor continuously throughout the presentation, its just free marketing for them and detracts from your project. Geir Magnusson made the same mistake a few years ago when I saw him give a speech on Geronimo. I was able to shake hands with Jacek after the talk and I thanked him for mentioning us so many times.

After the conference, I hung out with the JBoss guys and their wives and girlfriends in the Jewish sector of Krakow. I experienced what they called Polish fast food (guys name please again!) and had something that looked like pizza on a half loaf of soft bread, but it was much more tastier and satisfying. We had an early night because I was tired from the long day and they had all gotten up at around 4am to take their train to Krakow from Warsaw.

The Weekend

The rest of the weekend was sight-seeing. Since the JBoss guys were staying a few minutes from me, Anna, one of the conference organizers I talked about above, picked me up to meet them at the Wieliczka Salt Mine near Krakow. There was a time miscommunication and the JBoss guys actually got there an hour before we did and did the tour without us. The ironic thing was they ended up going to the English tour and I ended up going to the Polish one. The Wieliczka Salt Mines were really cool. These 900 year old mines had beautiful statues carved right out of the stone and a lot of windy passages that reminded me of the Lord of the Rings. The prettiest part was the Chapel of Saint Kinga which was again, carved right out of the stone. Afterwards, Anna dropped me off with the JBoss guys and they took me out to a another traditional Polish dinner where I ate too much. Afterwards we went to a cool bar in the Jewish sector of Krakow and had kamikaze shots and a bunch of beer. Later we went back to the place they were staying and I was introduced to Polish Vodka. *sarcasm* Thanks guys! *sarcasm*. The night ended with Tomek (a JBossian) and I getting into a heated, Vodka-induced argument which we laughed about heartily the next day.

On Sunday, again Anna took some time out of her weekend to show me and the JBossians around a little. In the late morning she and and one of her friends picked me up and took me to the flea market in Krakow. American antique collectors would have drooled over all the old stuff that was there. After also going to the beautiful, and sad, Jewish cemetery there, we met up with the JBoss guys for lunch which followed with a tour of Krakow’s castle. I truly liked Krakow. It was a beautiful city. I hope to take the wife there someday when our kids our older and we can just dump them off at their grandparents for a week or so.

WOW! Hope this wasn’t too much information. JDD Krakow was a great trip and I was honored that PROIDEA pegged me as a speaker. If I have something interesting to talk about I hope they ask me back next year.

 

The rise of meta-annotations

2 Comments

In reading lately about the new Web Beans specification, I started to realize how much meta-annotations change things. What are meta-annotations? Meta-annotations are simply annotations that annotate other annotations. How could they be used?

Shorthand

Remember a few blogs back when I criticized the @HttpMethod annotation for JSR-311? I said I’d rather have a typesafe annotation represent GET, POST, etc… than a String parameter to @HttpMethod. Marc Hadely, the spec lead, had an idea to allow @HttpMethod to be a meta-annotation stead:

@HttpMethod("GET")
public @interface GET {}

You could apply @HttpMethod to any annotation and it would be triggered by indirection. The idea being, that if HTTP added methods (like WebDav), then they could easily be defined using @HttpMethod as a meta-annotation. They didn’t like my idea of combining @Get with @UriTemplate, but, what if you took meta-annotations even further? …….

Behavior composition

Hmmm, can you annotate an annotation parameter? I tried it out, and you can. Now, what if we also allowed @UriTemplate to be a meta-annotation on a annotation parameter? Then I could have the @GET(“/foo/bar”) REST annotation I always dreamed of:

@HttpMethod("GET")
public @interface GET {
   @UriTemplate String value();
}

The idea would be that @UriTemplate, empty, on an annotations parameter would trigger the extra @UriTemplate behavior when my custom @Get method was applied. So what’s my point here? Maybe this could be used to get rid of annotation creep. Maybe people could use this as a mechanism to define their own idioms and bind their idioms to various competing component models? Just something to think about…

Meta-annotations and AOP

During the EJB 3.0 jsr of EE 5, Gavin wanted to add the ability of allowing @Interceptors to be a meta-annotations. This would allow you to have user-defined annotations that triggered behavior. Take the JBoss Business Activity Framework. The implementation of it could easily be done within EJB 3.0 interceptors. The problem is that to apply BA interceptors in the current EJB 3.0 specification you’d have to bind them with an ugly @Interceptors annotation on the bean class or with XML within ejb-jar.xml. Wouldn’t it be cool if @Interceptors was a meta-annotation? Then you could do something as simple as:

import javax.interceptor.Interceptors;

@Interceptors(org.jboss.ba.BAInterceptor.class)
public @interface BACompensatedBy {
   public String value();
...
}

If the EJB container could resolve @Interceptors as a meta-annotation, then just using and applying the @BACompensatedBy annotation would be enough to trigger the behavior. Gavin, Seam, and Web Beans took this idea further, by defining a @InterceptorBindingType meta-annotation.

@InterceptorBindingType
public @interface BACompensatedBy {
   public String value();
   ...
}

You would then bind an interceptor class by apply the @BACompensatedAnnotation to your actual interceptor class

@BACompensatedBy @Interceptor
public class BAInterceptor {
   @AroundInvoke
   public Object registerCompensation(InvocationContext inv) throws Exception {...}
}

If you think about it, this could have a profound impact on AOP in that pointcut expressions begin to only be used in edge cases. If you’re implementing aspect-oriented annotations, no quirky, unreadable pointcut expressions are needed. Just use the binding annotations. If you’re using pointcuts to define integration points into your application, instead, remove these in favor of simple annotations that you move around as you refactor your application.

Seems to me that meta-annotations have a lot of potential.  Wouldn’t it be cool if all Java EE annotations were allowed to be meta-annotations?  Just another thought.  If you know any other uses, let me know here. Thanks.

Oh, and BTW:

GO SOX!

Newer Entries