Веб-системы должны выполнять все более сложные функции, многие из которых на стороне клиента, но значительная часть этого требует сложной разработки на стороне сервера. Эта сложная веб-разработка зависит от реализации архитектурных принципов RESTful, аналогичных тем, которые можно найти в Ruby on Rails . Новая волна разработки RESTful направлена на Entprise под видом веб-сервисов RESTful. Разработка корпоративных систем RESTful становится все более простой как для корпоративных сервисов, так и для веб-лагерей с помощью таких сред, как Grails , JAX-RS , WCF , ADO.Net Data Services.и новая партия статически типизированных технологий RESTful MVC, основанная на корпоративных технологиях. Фреймворки, не относящиеся к сценариям, определенно имеют некоторую догоняющую работу, но все они идут хорошо. Недостаток сценариев в средах REST состоит в том, что они не имеют языковых функций, которые ускоряют разработку сценариев разработки, но есть также множество примеров хорошей разработки, перенесенной из решений scriptng в их сценарии, не поддерживающие сценарии.
Похоже, что REST еще не попал в Enterprise в значительной степени, но развитие сред RESTful для Big Boys, вероятно, вызовет интерес Enterprise в ближайшие месяцы и годы.
I’ve come across quite a few interesting features in various RESTful frameworks. I’ve also thought up some potentially interesting features in the development that may or may not exist yet that will probably prove useful in an enterprise; I may be playing the role of Astronaut Architect, so please feel free to flame any of my ideas that you find lame.
-
Centralized + Localized URL Mapping Mechanisms — Being able to describe a RESTful endpoint via an annotation (localized URL Mapping) is really fantastic. However, annotations are static and can limit reusability. For example, let’s say I have a furniture e-commerce application. I may want separate URLs for sofas («/catalog/sofas») and chairs («/catalog/chairs») and still have a single back-end service/controller object servicing them. Grails can do this via it’s URL Mapping mechanism. Spring MVC also has some built in mechanisms for this. I’ve worked with an awesome in-house regex-based, hierarchical URLMapping utility, that among other things, converts RESTful URLs («/catalog/sofas/5921») to a format our MVC framework supported («/catalogController.do?type=sofas&id=5921»).
A centralized URLMapping/dispatching system also has a few more advantages, like a natural place for interception techniques and allowing for convention-over-configuration.
-
Multiple types of REpresentation — JAXB (JAXB 2.0) and XStream can both transform objects into XML, JSON or other formats. They are extensible and configurable. One of the two techonologies I mentioned can at the core of just about every single RESTful and SOA java technology.
-
Integration with text generating technologies — For example: JSP, FreeMarker, Velocity, SiteMesh, Tiles and others. Preferably, I’d be able to choose the technologies that best serve my needs. You’ll likely need an HTML REpresentation in a RESTful environment. Even pure «RESTful Web Service» (such as JAX-RS) scenarios can benefit from this type of integration. Bill de hÓra uses StringTemplate to create relatively complicated XML in a JAX-RS environment, and Paul Sandoz of the JAX-RS and Jersey (the JAX-RS reference implementation) teams shows how Jersey integates with JSP. Scripting languages usually have complex String manipulation built into the language don’t need this type of integration as much, even though they’re likely to have such integrations. Groovy GString, Groovy XML and Scala’s built first class XML are prime examples of scripting language features that make XML a breaze.
-
DOM Integration — I found that programmatic DOM manipulation is a pretty powerful complementary tool to domain object/POJOs. Bill de hÓra’s example of converting of an object into a different format could have just as easily been performed in a non-template based solution. Groovy’s DOM-like builder functionality is in fact one of the reasons that Groovy is so good at writting XML. A scripting environment’s language features may be a bit more elegant, but a well designed DOM API can come pretty close in elegance.
My preference for this type of manipulation is Dom4J. I do wish that Dom4J would be updated for a JDK 5+ environment (specifically generics), but that would just be icing on the cake. I haven’t played around with the Dom4J/XSteam integration, but it would be pretty slick to create a Dom4J document and write out JSon using XStream.
IMHO, DOM-to-REpresentational format, would be a great asset to an existing Object-to-REpresentational format for complex conversions between an internal domain model and an external one. Is «Object <-> DOM <-> REpresentation» possible with JAXB and XStream technologies? It may not be a commonly requested feature, but IMHO it would be a powerful addition.
-
Binding to REpresentation should allow POST/GET parameters in addition to XML/JSon — Servlets allow access to GET and POST data via a uniform API. AJAXy and Servicey systems use POST of JSon/XML data and GETs with parameters placed directly from the URL. I have plenty of legacy end-points (a.k.a. Controllers) that I’d love to use in a RESTful/Ajaxy way, but can’t because of differences between the two POSTing techniques. (Note: I do have a solution for the URL parameters via the Centralized URLMapping). Shouldn’t
order.customer=239852
<order><customer>239852</customer></order>
I did have a hack to bridge the two communication mechanisms, but I’d rather have had an integrated, well thought out solution.
-
Validation and Exception Handling — There are (at least) two forms of validation that are required to ensure proper behavior: 1) structural validation (the client passes along the right set of data, data sizes are correct) and 2) server-side business validation (For example: «you must have a unique user id,» and «you’re not authorized to access this data»). Communication of some of those errors can be performed through published interfaces (WADL), through status codes (401 = Not Authorized) and through messaging expressed in REpresentational formats (similar to Grails’ validation).
-
Configurable REpresentational Negotiation Strategy — I should be able to tell the system that I’d like an extension (XML — .xml, JSON — .json, RSS — .rss, HTML — no extension) to be how the client and server negotiate content type (content_type=XML/JSon/YAML/RSS). I should also be able to use a GET/POST parameter or the «accept» header (text/html, application/rss). I should even be able to handle more than one strategy.
-
MVC RESTfully Smart View — AFAIK, developing a JAX-RS application, for the most part, consists of developing client-server «service» methods. You can apply annotations to describe how to REpresent the return value to the client. For example:
@Path("/customerservice/")
@ProduceMime("application/xml")
public class CustomerService {
public CustomerService() {
}
@GET
public Customers getCustomers() {
......
}
...
}Paul Sandoz of the JAX-RS and Jersey teams shows how Jersey implements MVC. While MVC may be possible in Jersey, it doesn’t look nearly as robust as a full-blown MVC approach. I could be wrong, but AFAIK, If you want to expose your external domain model as both JSon or XML across the board in a JAX-RS, you’d have to create duplicate methods for each domain type/VERB combination to achieve that overall affect. I’m not sure if you can return more than one value to be rendered in JAX-RS. What happens if you need to render a Web Form with some collateral data, such as the ubiquitous State pull down? What happens if you new to show more than one type of value in either HTML form or XML form?
It’s theoretically possible for an MVC system to have a «Smart View» that would be able to chose between rendering types based on context. This can work in conjunction with your REpresentational Negotiation Strategy. The «Smart View» can determine if the URL has a .xml extension or an XML «accept» header. Theoretically a «Smart View» can incorporate a custom data conversion strategy (either DOM manipulation or converting the result from one POJO to another POJO) and then render the result based on the REpresentational Negotiation Strategy.
There are definitely trade-offs between JAX-RS’s client-server approach and this theoretical «Smart View» MVC. Client-server approaches are much simpler to understand. Full-blown MVC frameworks have a lot more capabilities and much more complexity. The popular Java based MVC frameworks, however, don’t currently easily support the types of REpresentational functionality found in JAX-RS, but that’s changing rapidly. Spring @MVC is going to get a RESTful upgrade in Spring 3.0, and frameworks such as Mattress (Spring based) and Fulworx (XWorks based, like Struts2) are paving the RESTful way with innovation. I assume that there will be more MVC-type capabilities built on top of JAX-RS. I’ll definitely be watching this space.
-
Domain Addressability — This is a bit of a tough requirement. The domain model is controlled by some persistence mechanism (JPA for example), and may require numerical ids. The persistence mechanism is usually the «bottom» layer, meaning it’s the farthest, execution-wise, from the origination call, and is usually an internal, abstracted implementation detail. External systems need to be able to identify the data through a URL that has different dynamics and access rules than the persistence layer. For example, take this fragment of a shopping cart application:
<order total="...">
<customer id="http://mycompany.com/customers/239852" />
<items>
<item id="http://mycompany.com/catalog/tables/49863"
quantity="1"/>
<item id="http://mycompany.com/catalog/chairs/28352"
quantity="4"/>
</items>
</order>If this data had to end up in a relational database, you’d have a whole bunch of tables that represent the entities and the relationships, probably with numeric ids and no URLs. It’s also very likely that the «tables» and «chairs» URLs map to the same database table. Mapping between URLs and internal domain is non trivial. I haven’t seen a consistent strategy for handling this mapping; that might be because I’m unaware of existing techniques…
We had some complex addressibility requirements on my last project because of SEO and Informational Architecture needs. We broke down our URL structure based on the meaning of the content to the end user; we didn’t base our URL structures based on the internal representation of the content. We centralized the URL creation logic and exposed it via a Service object and a JSP tag. To add on to that, we also had guided navigation based on previous contexts. If you came to see a contemporary chair through the «style» catalog, we put some information into URL parameters so that we’d show other furniture of similar styles in the sidebar, instead of the default of other chairs.
The Domain Addressability strategy should also work well with the REpresentational Negotiation strategy. For example, if you had a URL of http://mycompany.com/order/1281.xml, the controller should return something like:
<order url="..." total="...">
<customer id="http://mycompany.com/customers/239852.xml" />
<items>
<item id="http://mycompany.com/catalog/tables/49863.xml"
quantity="1"/>
<item id="http://mycompany.com/catalog/chairs/28352.xml"
quantity="4"/>
</items>
</order>I haven’t seen any existing implementations of this idea. Any help suggestions or existing implementations of this idea would be appreciated
-
Object REpresentation Mapping (ORM) — There should be easy ways to have end-to-end integration between the domain persistence technology, REpresentational transformer, and service end-point/URL. This idea has three aspects to it: 1) easily exposing data from a persistence store through REST, 2) easily finding granular data over REST 3) RESTful data «queries.»
Exposing and reading a single granular entity (@Entity?) or a java.util.Collection of entities via a RESTful end-point should either come out of the box, or should be extremely easy to implement. In Grails/Rails, you can do this by pointing a script at a database. In MS ADO.NET Data Services, you can do that through some configuration and writing some ORM PONOs. How easy is that to do in JAX-RS? It looks pretty straight forward to me, if you’re using NetBeans 6.1
It’s the client side engine that really makes ADO.NET shine. A colleague at SunGard Consulting Services, Michael Heydt, said:
Having had my head buried in Silverlight for most of the year, I’m going to go out on a limb and make a bold statement that the real important part of REST in WCF / ADO.NET Data Services is really to support Silverlight based applications. Sure, AJAX is in place and it will support that, but it really seems to me that the future is Silverlight back to REST enabled data.
Having worked exclusively in HTML based technologies, I don’t necessarily agree with the support focus of RIA, but I do agree with the general sentiment about the usefulness of the technology stack.
IMHO, It would be pretty interesting to have a Hibernate-like proxying client-side solution that could automatically retrieve lazily loaded data on request over REST. Qi4J RESTful implementation using Semantic Web technologies such as RDF and SPARQL is definitely a method worthy of exploration.
-
Integrated Security — Security is one of the top concerns about ADO.NET’s RESTful services. REST doesn’t say much about how you go about performing secure operations. Luckily, there definitely are plenty of methods a web-based (and there-fore inherently apply to REST over HTTP) applications can be secured. A RSTFul development framework should provide a way of integrating those security methods. Security concerns will definitely limit RESTful Enterprise deployment.
-
Configurable Client — RESTful environments can very likely be a collection of interlocking systems rather than a single server. A good client is indispensable. A good client knows a «logical name» of the RESTful service it needs. Bottom line is, environmental configuration is pretty darn important in a RESTful system.
JAX-RS doesn’t have a standardized client API yet, but the three implementations of JAX-RS that I know of (CXF, Jersy and RESTEasy) all have client APIs.
-
Cachabilty — Caching is a big part of a RESTful architecture, and should be supported by both the server and the client of a RESTful environment.
A server-side development infrastructure should include the ability to set caching headers and ETag headers. Doing that via annotations would be pretty consistent with most of the newer frameworks.
A client-side development infrastructure could include the ability to cache results based on Caching headers and ETags. A browser does this. I’m not quite sure which existing caching technology could be used for RESETful client-side caching. I’m used to EHCache, usually with Hibernate, where the application server (the database’s client) controls both the caching strategy (should an object be cached, how long to cache objects, versioning) and the caching implementation (performing the caching to disk/memory); RESTful caching requires the server to determine cache strategy, and the client to determine implementation. I don’t know if that kind of functionality exists.
-
JS framework integration — DWR does some pretty amazing stuff with converting POJOs into JavaScript accessible services and JSon data. It also does some pretty slick performance enhancements by controlling aspects of both the client-side and server-side. I would imagine that it could theoretically integrate with JSR 311 compliant servers.
I’ve put up quite a few ideas in this article about what I’d like out of a RESTful development infrastructure. Some are ideas that have been implemented, and some may not even be easily implementable.
If you have any other ideas about a RESTful environment, or some other comment about the ideas here, please let me know. The ideas that I’m most interesting in fleshing out are the Domain Addressability and Object REpresentation Mapping (ORM) ideas. The Cachable Client idea isn’t that far behind, and integrates with the ORM idea. Again, feel free to flame, I don’t generally moderate the comments.