The poor JAX-RS Request Dispatching Algorithm

5 Comments

As we’re rolling out Resteasy 3.0, we have to pass the JAX-RS TCK.  The good thing about this is that the TCK has grown massively is size and has a lot more test coverage for all old and new features of JAX-RS.  It allowed me to uncover a few bugs I would not have found without the TCK.  An unfortunate downside the TCK also got a lot stricter in some of the weak areas of the JAX-RS specification, particularly the request dispatching algorithm.  I’ll be blunt, the algorithm is poor.  IMO, the old spec leads made a huge mistake in introducing implementation details to the specification and now we have a poor algorithm we are stuck with.  Us vendors cannot innovate and improve it because the TCK has backed us into a corner and the licensing fine print of Java EE makes it really hard for us to ship things that diverge from the spec.  Here are a bunch of problems that used to work in Resteasy, but will no longer work because the TCK tests every fine detail of the JAX-RS matching algorithm.

  •  The @Path annotation at the class level is matched first before matching any resource methods.  Only classes with the best and exact regular expressions are picked.  Then the rest of the request is matched with remaining methods.  So this won’t work anymore with a spec compliant algorithm:
Request: OPTIONS /foo

@Path("/foo")
public class Foo {
   @GET
   public String get() {...}
}
@Path("/{.*}")
public class OptionsDefault {
   @OPTIONS
   public String options() {...}
}

Earlier versions of Resteasy would match OptionsDefault.options().  Now, this method will not match according to the spec rules and you’ll get the default JAX-RS OPTIONS behavior.

  • Locators are never resolved if there are resource methods that match the request.  For example
PUT /foo/sub

@Path("/foo")
public class Foo {
   @GET
   @Path("sub")
   public String get() {...}

   @Path("{id}")
   public Locator locator() { return new Locator(); }
}

public class Locator{
   @PUT
   public void put() {...}
}

You’d think that the request would resolve to Locator.put() but you’d be wrong! Because there is a resource method whose path matches the request, but not the method you’d get a 405 response from the server. What’s interesting if you flip the expressions, a PUT request would work, but a GET request wouldn’t!

PUT /foo/sub

@Path("/foo")
public class Foo {
   @GET
   @Path("{id}")
   public String get() {...}

   @Path("sub")
   public Locator locator() { return new Locator(); }
}
  • It is possible to have poorer matches
GET /fart
Accept: text/plain

  @GET
  @PATH("foo") 
  @Produces("text/plain") 
  public String get1() {} 

  @GET
  @Path("{text}") 
  @Produces("text/plain") 
  public String get2() {} 

  @GET
  @Path("f{text}") 
  @Produces("text/*") 
  public String get3() {}

You would think that GET /fart would match the get3() method because it is more specific path, but you’d be wrong.  Because get3() has a less specific @Produces get2() would match.  This is weird because the spec originally tells you to sort expressions on a best-match basis but then ditches this information to match Accept headers.

Another related note is the default returned media type.Right now the default is dependent on the deployment.  If there is no Produce header, then the returned media type defaults to a union of the Accept header and explicit media types of all available MessageBodyWriters.  There goes your portability!  Instead, implementations should be allowed to specify their own default or even make it configurable.  But, of course we can’t do that!

Granted some of these issues are edge cases, but IMO, some are not.  The specification has 2 pages on english/pseudo-academic algorithm syntax to describe this very complex, but poor algorithm.  Users will get frustrated trying to understand it.  The experts themselves argued for days on interpretation of the specification.  Users will scratch there head wondering why certain classes will match and some won’t and blame the vendor’s implementation.  Resteasy had at least 4 user-reported regression tests that failed as a result of following the specfication matching algorithm religiously.  I know these users will be back complaining that Resteasy 3.0 does not work for them when Resteasy 2.3.x did.

Java EE wins over Spring

169 Comments

The past 1-2 years since the release of Java EE 6, you’ve seen a lot of articles like this latest on TSS that talk about the niceities of Java EE 6’s component model over Spring and how Spring is now legacy.  Yup legacy.  Who would have thought it?  (other than me of course 😉 ) I remember internal JBoss emails 4-5 years ago arguing whether we should give up on promoting Java EE as a component model (aka on EJB) and just concede to Spring.  Now, 4-5 years later, Java EE 6 has answered the challenge and is a viable, rich, integration technology.  So what happened?

Spring always depended on Java EE

Spring was and has always been a wrapper over core middleware infrastructure: ORM, Transactions, Messaging, HTTP.  It always depended core Java EE specs like JPA, JTA, JMS, and Servlet.  So, since you couldn’t deploy a Spring app without at least one of these core technologies/specifications, Java EE stayed in users minds.  There was always the opportunity that Java EE could get its act together in component model development.  While Rod Johnson always tried to position Spring as a Java EE alternative and JBoss killer, the Spring “platform” was never a true alternative to Java EE and JBoss, and in fact, couldn’t really exist without it.  IMO, this was a huge missed opportunity for the Spring folks.

Being the anti-Romney doesn’t work in the long run

J2EE was a machine with a huge massive install base.  A machine with a massive amount of money invested into it.  Java EE was its own market.  While Rod positioned himself over and over as the alternative to Java EE did he really think that this massive machine wouldn’t respond to the challenge?  While there are a lot of radical technology enthusiasts out there, the core Java constituency is pretty much moderate.  They are slow to adopt and tend to wait to see who is going to win the war over a long time.  Spring could not replace Java EE because technology wise, they were dependent on it.  All Java EE had to do was improve its component API message to the people, outspend Spring, and win over it in the long run.

Annotations were a game changer

The first thing that happened to shake Spring was the introduction of annotations in Java 5.  Annotations were a game changer.  Annotations were the opportunity to introduce mini-DSLs and pluggable keywords into Java.  Java EE 5 grabbed this opportunity with a huge facelift and refactoring of EJB and the introduction of JPA.  Basically, this was a standardization of Hibernate and its integration into EJB.  Complex EJB 2.x XML was replaced by few new Java keywords (well, annotations).  Simplicity ruled the day.  Middleware started to look more and more like a language feature rather than something hacked together via XML.  When annotations came out, I remember the Spring folks writing multiple blogs and forum posts about how evil they were.  IMO, they were just terrified of this new technology as it made much of Spring 2.x obsolete, and, well, much of Spring more complicated than Java EE 5.

CDI closed API hole

Thank you Gavin and the Seam folks.  CDI and Java EE 5 pretty much closed the technology gap.  Not only did they fill the integration holes that Spring exposed, they innovated far beyond what Spring had and created something new.  Beyond core IoC and DI, CDI’s event model was truly innovative and cool.

App Servers got their act together

Application server started to get their act together with regards to boot time.  It started with Glassfish and ended with JBoss 7.  Both of which can boot in a matter of seconds.  The whole Spring complaint that you needed Spring to mock out and test your code because app-servers started so slow was moot.

Arquillian made a mock of mocks

The final game changer was Arquillian.  One huge advantage Spring had was a unit testing story.  They gave you the ability to mock out core services like transactions and allow you to test application code outside of the application server.  This is huge for continuation integration and automated builds as well.  Combined with the fast boot times of JBoss 7 and Glassfish, you no longer have to hope your mocks will work when you actually run it in its real environment.  Arquillian allows you to run your unit tests in a real environment with real transactions, etc.  Personally I always despised mocks because they didn’t test in the environment you were going to run in.  I thought they were pointless and to this day, I refuse to use this testing pattern.

Anyways, in retrospect, I’m glad Rod and company were able to cash out with the VMWare acquisition before Java EE was able to regain its dominance.  SpringSource pushed Java EE to innovate and for that I’m very grateful.  For Java EE, it was either evolve or die.  They evolved, now its time for Spring to die.

 

Remember why we don’t have Java 7

22 Comments

This is a bit of a reiteration of my previous blog, but, I wanted to be a bit more clear:

Ask yourself this question…Why do we not have a Java 7 release?  Mainly it is because of Apache (not the developers, but the bureaucrats) filibustering the Java 7 vote in the JCP Executive Committee all because they didn’t want a Field Of Use restriction for Harmony.   They felt entitled to the Java brand just because they are Apache.  For those of you who don’t know the Field Of Use, (IIRC) was that Harmony wouldn’t have been able to be used within a mobile environment.  IMO, I’d much rather have had a Java 7 release than to lift the FOU restriction just to make one Apache open source project  happy.  I’m upset with my company for supporting this fiasco.

Another side point:

The “I’m leaving the JCP because it isn’t working” play that seems to be popular at the moment, is, IMO, a big slap in the face to those of us who have put a lot of time, effort, engineering, and dollars to improve the Java platform, specifically on the EE side of things.  Specifically, the Apache CXF project who have created a top-notch SOAP implementation, as well, of course the Tomcat effort.  For Red Hat, we’ve put huge amount of engineering time into EJB, JPA, JSF, CDI, JAX-RS, and Validation.  There are many other companies, individuals, and open source projects that have made similar contributions.  Those of us who cared enough about the platform (and Sun and Oracle are both in this camp) have improved and evolved Java EE so that it is viable platform into the next decade, despite the best efforts of the “Party of NO” coalition of non-contributors on the EC and on the Java EE JSR.

IMO, if you are unwilling to give up something to obtain the Java brand, if you’re creating competing technologies that you have no intention of bringing back to the JCP to be standardized, if you or your company are not consumers or implementors of JCP specifications, then, you probably should leave the JCP.  In fact, I encourage it, so that the rest of us can have less obstacles in moving the platform forward.

And we care why?

15 Comments

So, Apache leaves JCP.  Surprise surprise.  Their biggest contribution in the past few years has been to filibuster the Java 7 JSR, and is the primary reason why there is no final version of Java 7 (or 8) today.  I’m all for non-contributing members leaving the JCP.  Less noise, and more people, who actually care about the language and EE platform working on improving it.

JCP is Salvageable

14 Comments

In the wake of Doug Lea leaving the JCP, I just want to say that I think the JCP is salvageable.  This idea the JCP is an unworkable entity is plain and utter myth.  A myth propagated by those that want to see it fail (i.e. SpringSource) or those that want to create their own, and controlled, specification efforts (IBM), or those that are more interested in doing their own thing than collaborating with others (i.e. Google and SpringSource).  Don’t believe me?  Well, let’s discuss it a little more.

First case in point is JPA.  In J2EE 1.4 and earlier we had the crap that was CMP and its unloved and unwanted step-sister JDO.  The Persistence story and message within EE was divided, unclear, and (in CMP’s case) inferior and fundamentally flawed.  This allowed Hibernate to flourish and practically become a de facto standard.  If the JCP was broken and unworkable, we would have never been able to get JPA into the EE 5 specification.  JPA was such an important direction for the EE platform.  Firstly, it brought the innovations of using annotations, but more importantly it unified the platform bringing de facto proprietary implementations like Hibernate and Toplink under the EE umbrella, retiring CMP and bringing the EJB community into the fold, and finally, forcing a shot-gun marriage with the JDO crowd.  The platform needed this, needed this badly to remain relevant.

Second case in point is CDI.  Spring’s rise has always been more about EJB’s incompetence rather than any real technology.  Java EE had three huge holes to fill: injection/IoC, true integration across various specifications, and most importantly an SPI to be able to extend the platform and foster innovation outside the specification process within the Java community.  CDI filled all these holes.  The fact that little Red Hat who is dwarfed in market cap and marketing muscle by the likes of Google, IBM, and Oracle, could push such a game-changing specification through with all the political opposition in place, is a testament that the JCP does work and can work if the participants are willing to focus on technology.

Third, the JCP was already changing pre-Oracle acquisition.  It was already becoming much more open.  Specifications like CDI, JSF, Validation, and JAX-RS all were defined within a completely open process.  Many had open source RIs and TCKs.  Things were improving.

As far as Doug goes, its a big loss.  I know a few of my JBoss colleagues enjoyed working with him.  Personally, I think his departure was premature.   I don’t think the dust has settled yet after the Sun acquisition.  All Java JCP major participants knew that the JCP had to change.  We wanted change.  We still have to give Oracle the benefit of the doubt and, more importantly, time.  Time to get organized.  Acquisitions take time to settle (believe me I know).  From what I’ve seen, Oracle had in the past always been an innovator supporter on the EE specification process.  I don’t see why this couldn’t continue.  They have some good people over there that recognize innovation and want to move the Java EE platform forward.  Whether or not they will have say over the Oracle business people remains to be seen IMO.

Oracle and Java

5 Comments

Let’s face it.  We all knew Sun would get acquired.  The question was just when and by whom.  Now that its happened, and Oracle is the winner, I must say I like the situation better than if IBM had bought them.  Just from a EE specification perspective, IBM was always a bit reactionary when it came to anything new.  On EE 5, Oracle was a staunch ally in our push to get JPA through and a part of EE 5 (and thus retiring CMP and making JDO obsolete).  On EE 6, we’ve met a bit of resistence from them when it comes to the-spec-formally-known-as-Web-Beans, but they’ve been at least open to the idea.  Who knows how the Oracle business guys will want to deal with Java.  That is the wildcard IMO.  Should be fun… Interesting times.

RESTEasy 1.0.0.GA Released!

2 Comments

See more info on blogs.jboss.com.

Newer Entries

%d bloggers like this: