Hi Thiago,

This sounds like an interesting work, Thiago. I spent a fair amount of time getting my web application to push updates out from a Tapestry Service via WebSocket, but it would be great having the RESTful option too (for a possible, future mobile app). And all without having to employ an additional framework such as Spring REST.

Kind regards,

Chris Dodunski.


On 2021-10-09 11:04, Thiago H. de Paula Figueiredo wrote:
Hello, Tapestry community!

I've been working on something I really wanted Tapestry to have but haven't had a chance to implement myself until some time ago: proper REST support. And not do it by integrating with some other framework like Jersey or CXF
or by being a JAX-RS implementation, but by doing it in a very Tapestry
way: event handler methods, TypeCoercer for type conversions, everything being customizable by contributions to Tapestry-IoC services, return value
of event handler methods handled by ComponentEventResultProcessor
implementations, etc.

This is a work in progress, done in the "rest" branch, so I decided to
publish a snapshot (5.8.0-SNAPSHOT) so you can use it yourself and tell me
what you feel about it. All feedback is welcome!

Major points:

   - New page-level events are triggered after the "activate" event is
triggered (i.e. onActivate()) so you can write REST endpoints as regular,
   live-class-reloaded event handler methods.
- One for each supported HTTP method: GET, POST, DELETE, PUT, HEAD,
      PATCH.
      - Event name is onHttp[method name]. For example, onHttpPut.
      - New constants in EventConstants for each supported HTTP method.
- Activation context for REST event handler methods exactly in the
      same way as in onActivate().
      - Just like onActivate(), these new events are not triggered in
      components.
   - New service in tapestry-http (which is included by tapestry-core),
   RestSupport, with utility methods and <T> Optional<T>
getRequestBodyAs(Class<T> type), which returns the request body converted
   to a given type.
      - getRequestAsBody(Class) uses HttpRequestBodyConverter.
- Another new service in tapestry-http, HttpRequestBodyConverter, which uses an ordered configuration of itself, which provides conversions of
   request body to given types.
- Only one method, <T> T convert(HttpServletRequest request, Class<T>
      type);
- tapestry-http contributes one implementation, which is added as the
      last one in the ordered configuration, which uses TypeCoercer.
- Out of the box, it supports conversions to String, primitive types, JSONArray, JSONObject plus any other type that has a String -> type
      conversion available in TypeCoercer, directly or not.
- New annotation for page event handler method (onActivate(), onHttp*) parameters: @RequestBody, which receives the request body and converts it
   to the parameter type using RestSupport.getRequestAsBody().
- Think of it as @RequestParameter but for the request body instead of a
      query parameter.
      - Example below.
- New annotation for page event handler method (onActivate(), onHttp*) parameters: @StaticActivationContextValue("something"), for defining that method will only be called if that page activation context value matches a
   given string.
      - Example below.
- Parameters with that annotation still get their values set as usual.
      - This was built mostly for REST support, but it can useful for
non-REST situations too when a give activation context has a number of
      possible values and there's some logic tied to it.
- Automatic generation of Swagger/OpenAPI 3.0 REST API definition files.
      - OpenApiDescriptionGenerator service, which is an ordered
      configuration of itself.
- An internal implementation generates a base JSON object definition
      that can be customized by contributing more OpenApiDescription
      implementations.
      - Titles, names, summaries, etc can be provided by configuration
      symbols or message files (app.properties).
- Messages files are live class reloaded too, so all changes done
         to the REST endpoint event handler methods and the
corresponding messages
         are live reloaded.
         - Formats for message keys and described below.
      - Parameter descriptions not implemented yet.
         - It will support query parameters and path parameters.
      - [Not implemented yet] Embedded Swagger/OpenAPI viewer (i.e. the
   right pane of https://editor.swagger.io) hooked directly to the
   definition file generated by OpenApiDescriptionGenerator
      - It's going to be a separate subproject/JAR to avoid bloating
      projects not using the viewer


@StaticActivationContextValue example:

    final private String COMPLETED = "completed";
    final private String CLOSED = "closed";
// Only called if first page activation context value is "completed"
    @OnEvent(EventConstants.ACTIVATE)
void completed(@StaticActivationContextValue(COMPLETED) String state,
int id) {
        ...
    }

    // Only called if first page activation context value is "closed"
    @OnEvent(EventConstants.ACTIVATE)
void closed(@StaticActivationContextValue(CLOSED) String state, int id)
{
        ...
    }

REST endpoint event handler method example:

    Object onHttpPatch(
            @StaticActivationContextValue("subpath") String subpath,
            String parameter,
            @RequestBody String body)
    {
        ...
    }

    @OnEvent(value = EventConstants.HTTP_DELETE)
Object delete(@StaticActivationContextValue("subpath") String subpath,
String parameter)
    {
return createResponse(EventConstants.HTTP_DELETE, null, parameter);
    }

Happy coding!

--
Thiago

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tapestry.apache.org
For additional commands, e-mail: dev-h...@tapestry.apache.org

Reply via email to