Shoehorning Java into RESTful Design
What are the primary reasons you code in Java in your enterprise IT shop? Be honest now:
a) We have solid Java programming skills on staff
b) We have a lot of existing Java in production we’ve coded over the years and/or we’ve made a significant investment in Java-centric infrastructure (ESBs, application servers, etc.)
c) Of all the languages and programming and execution environments we could have chosen, Java is the best suited for addressing our specific bespoke software challenges, independent of current skill sets, infrastructure, or existing production code.
If you selected a and/or b but not c, then you have what we like to call a legacy Java problem. There are other, perhaps more modern languages that would better suit your needs, but because of your existing investments in people and technology, you’ve essentially shoehorned Java.
All is not lost, however. The ongoing efforts of the Java Community Process (JCP) have augmented the capabilities of the Java ecosystem in order to tackle a wide range of new problems and situations. This ongoing work on Java may continue to meet your needs for years into the future.
But then again, maybe not. The heavyweight model-view-controller (MVC) architecture of Java EE, or simply the object-oriented context of Java more broadly may not support alternative architectural approaches. In particular, if you are building a distributed hypermedia application, then a RESTful architectural approach will likely better meet your needs than a Java-centric architectural approach.
JAX-RS to the Rescue?
But wait, you Java geeks out there are saying, can’t we have both? Wouldn’t it be ideal if we had a Java-centric way of building RESTful applications? After all, the JCP has worked to address Java’s support for REST, which led them to the Java APIs for RESTful Services (JAX-RS) standard. Now we can build RESTful applications simply and easily in Java, right?
Unfortunately, JAX-RS is a classic example of shoehorning. It adds some RESTful capabilities to Java, but fights the RESTful architectural style every step of the way. Case in point: the Hypermedia as the Engine of Application State (HATEOAS) constraint. JAX-RS 1.1 didn’t support hypermedia at all, which essentially meant that we would have to simulate HATEOAS characteristics by utilizing core Java capabilities. To make JAX-RS fully RESTful, you would have to design applications that satisfied all of REST’s architecture constraints, compensating for those features that did not have adequate support during development. JAX-RS 1.1 provides adequate support for satisfying some REST architecture constraints, but punts on HATEOAS.
JAX-RS is an adequate API for implementing RESTful Services in Java, but JAX-RS version 1.1 has no built-in support for hypermedia. In JAX-RS 2.0, expands hypermedia support. The JCP has added hyperlinks and client support to the forthcoming JAX-RS 2.0, but even so, developers will find JAX-RS an immature tool for building distributed hypermedia systems.
More Challenges with JAX-RS
To simplify the development and deployment of RESTful Services, JAX-RS uses Java annotations. There are Java annotations to express REST resources, media types, access methods, etc. There are no annotations to express hyperlinks. You have to design those yourself.
As another example, consider standardized Service contract and loose coupling design principles. RESTful Service contracts require the unification and standardization of the resource identifier syntax and conventions for expressing and accessing resources. In the case of RESTful Services, you should design URIs in a consistent way. Furthermore, URIs should be opaque to reduce coupling between consumers and RESTful services. JAX-RS allows such consistency, but doesn’t encourage or enforce it.
It’s also important to standardize custom media types whenever possible, and you must also select which standard media types and custom media types you should use. Furthermore, the Service discoverability design principle requires having hypermedia controls in place, based on the REST HATEOAS design constraint. Discoverability provides a way of making the protocol self-documenting. JAX-RS doesn’t help with either of these design principles.
As a final example of shoehorning, consider the two different types of links that JAX-RS defines: transitional links which describe optional next actions and structural links which provide optional detailed information. Transitional links tell a client where to proceed next, while structural links help to shorten representations in order to avoid aggregate data. Details are replaced by links. Transitional links have some support in JAX-RS 2.0, but structural links are not supported due to their level of complexity.
So, why have structural links in the first place? The answer: we’re trying to shoehorn the Java object structure into hypermedia. If we simply take a Java object and convert it into hypermedia, we end up with links that represent all the various method calls on the associated object instances, resulting in excessively large, complex representations. Instead, JAX-RS encourages transitional links which enable the client to drill down to the underlying aggregate data. But if we weren’t handcuffed by the Java object structure in the first place, we’d never bother with transitional and structural links. Instead, we’d design our hypermedia applications to support discoverability. In other words, a core Java pattern becomes a hypermedia antipattern.
The ZapThink Take
It’s quite common for developers to rush to developing Services without first understanding the design of their final product. It is especially important when we are developing RESTful Services to have a well-architected, comprehensive design for developing Services that follow RESTful architectural constraints. However, to develop a good RESTful Service takes more than a good development tool or coding best practices accumulated over time.
People are often confused while developing with JAX-RS and thinking REST. JAX-RS is not REST design; rather, JAX-RS should support good RESTful design. Furthermore, the use of JAX-RS API does not lead to the creation of fully RESTful Services unless you have completed proper RESTful design beforehand. The design has to ensure that you have satisfied all RESTful architecture constraints.
Finally, established SOA governance should include policies and processes related to the endorsement of RESTful architecture principles. Those policies should cover design requirements and policies that you have established for satisfying RESTful design principles. But without adequate architecture, all the coding in the world won’t lead to proper governance.
About Leonid Felikson
Leonid Felikson has over 25 years of experience in software design, development, and implementation of large scale enterprise distributed systems, including consultation for both the government and private sectors. He has a diversified background in Information Systems and Enterprise Architecture. For the past 12 years, his focus has been on distributed computing; systems analysis, design, and integration; web services patterns and technologies; and service-oriented architecture and practices.
Mr. Felikson has extensive hands-on experience in product development and architecture in the software industry and he is a named expert in the field of distributed computing. He is a thought leader in providing the best solutions in IT strategy and in developing and utilizing SOA adoption enterprise-scale programs and SOA roadmaps. He is an innovator in establishing practices of modeling, designing, developing, and deploying services, performing both leadership and technical roles in delivering enterprise-scale applications and business process integration implementations.
Mr. Felikson devotes his time to knowledge sharing and education, mentoring and evangelizing SOA concepts and SOA practices. He has taught courses and seminars on the principles of operating systems and computer programming, as well as database concepts and design, data structures and algorithms, and software architecture and methodologies at a variety of public and private organizations.
Mr. Felikson has extensive teaching experience, working with a variety of schools and colleges, including serving as faculty at Johns Hopkins University for the last 11 years. He has developed curricula and taught courses within the CS and IST graduate programs at JHU. Since 2005, Mr. Felikson has been a contributing member of WS-I (www.ws-i.org), participating and contributing to the development of the WS-I Basic Profile 1.2 and the WS-I Reliable Secure Profile 1.0. Mr. Felikson received his B.S. and M.S. in Computer Science from the Ural Polytechnic Institute, in Russia.
Mr. Felikson is a Licensed ZapThink Architect and Certified ZapThink Trainer, and will be conducting Licensed ZapThink Architect courses in 2013.
Photo credit: David Pursehouse