On Sun, Oct 10, 2021 at 9:22 PM Christopher Dodunski (Tapestry) <
chrisfromtapes...@christopher.net.nz> wrote:

> Hi Thiago,
>

Hello!


> This sounds like an interesting work, Thiago.


Thanks! I know it's been very interesting work for me to implement so far.
:D


>   I spent a fair amount of
> time getting my web application to push updates out from a Tapestry
> Service via WebSocket,


Interesting. A Tapestry (probably Tapestry-IoC, actually) integration with
WebSocket is something I have in my mental backlog but couldn't investigate
yet.


> 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.
>

Indeed. And it also has the advantage of reusing what you already know
about Tapestry, so you'd need to learn just a bit of new stuff instead of a
whole other framework.


>
> 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
>
>

-- 
Thiago

Reply via email to