Overview
Since version 5.8.0, Tapestry provides out-of-the-box support for writing REST endpoints as regular event handler methods in page classes. They work in the same way the activate
event (i.e. onActivate()
methods) work, including how event handler method parameters work. The @RequestBody
annotation was created so event handler methods can access the request body. The @StaticActivationContextValue annotation was created so you can write event handler methods that are only called when one or more parts of the URL path match given values. Both annotations are not REST-specific and can be used in any event handler method. A new subproject/JAR, tapestry-rest-jackson, automates the use of Jackson Databind to make JSON conversions. tapestry-Swagger/OpenAPI 3.0 descriptions are generated automatically and can be easily customized. A new subproject/JAR, tapestry-openapi-viewer, provides an out-of-the-box viewer for the generated OpenAPI description using Swagger UI. For a Tapestry REST support example project, check out https://github.com/thiagohp/tapestry-rest-example.
Some important warnings:
- Tapestry's REST support isn't an implementation of JAX-RS, so they expect any of its concepts to work here. It's REST implemented in a Tapestry way.
- REST endpoint event handler methods in components are ignored just like
onActivate()
is.
The following HTTP methods are supported:
HTTP method | Tapestry event name | EventConstants constant name | Event handler method name |
---|---|---|---|
GET | httpGet | HTTP_GET | onHttpGet |
POST | httpPost | HTTP_POST | onHttpPost |
DELETE | httpDelete | HTTP_DELETE | onHttpDelete |
PUT | httpPut | HTTP_PUT | onHttpPut |
HEAD | httpHead | HTTP_HEAD | onHttpHead |
PATCH | httpPatch | HTTP_PATCH | onHttpPatch |
Writing REST endpoints
Writing a REST endpoint in Tapestry is exactly the same as writing onActivate()
method in a page class. Everything is the same: parameter handling, returned value processing, precedence rules, class inheritance, URLs, etc. If you know how to write onActivate()
methods, you already know almost everything you need how to write a REST endpoint event handler. There are only 2 small differences between onActivate()
and REST endpoint event handler methods:
- REST event handler methods are invoked after the
onActivate()
. - The event name is different, according to the HTTP method to be handled.
So, for example, if you want a REST endpoint with URL /userendpoint/[id], supposing the id is a Long
, handling the GET
HTTP method, you can just write the following page class and event handler:
public class UserEndpoint { Object onHttpGet(Long id) { // It could also be @OnEvent(EventConstants.HTTP_GET) Object anyMethodName(Long id) (...) } (...) }
The example above could also be written using the @OnEvent
annotation and would work the same:
public class UserEndpoint { @OnEvent(EventConstants.HTTP_GET) Object getById(Long id) { // or any other method name (...) } (...) }
Reading the request body with @RequestBody
Many times, specially with POST, PUT and PATCH requests, the data is sent through the request body. To get this data, the event handler method needs to add a parameter with the @RequestBody
annotation. It has a single property, allowEmpty
, with false
as its default value.