I'm sorry, I forgot to include the logic for Swagger/OpenAPI message and
configuration symbol lookups: Running the webapp with logging at debug
level, you'll see entries from DefaultOpenApiDescriptionGenerator showing
the message keys and configuration symbols being looked up.


   - Everything is looked up by message first, configuration symbol second.
   Symbols use the tapestry.[message key] format.
      - Exception: openapi property is only looked up by symbol
   - When building a message key, if it's based on a path, the starting
   slash isn't removed.
      - Example: openapi./something.head.summary
   - When building a message key, HTTP method names are lowercased.
   - openapi:
      - tapestry.tapestry.openapi-application-version (no message lookup)
   - info.title:
      - tapestry.openapi-title
   - info.description
      - tapestry.openapi-description
   - servers
      1. BaseUrlSource.getBaseUrl(false) (base HTTP URL)
      2. BaseUrlSource.getBaseUrl(true) (base HTTPS URL)
   - tags. One tag automatically generated tags for each page:
      - name:
         1. openapi.[fully qualified class name].tag.name
         2. openapi.[class name].tag.name
         3. Class name (unchanged, not looked up)
      - description:
         1. openapi.[fully qualified class name].tag.description
         2. openapi.[class name].tag.description
      - Each page tag is automatically applied to all paths handled by the
      page.
   - paths property (REST endpoints). For each path:
      - summary:
      *openapi.[path].[HTTP method].summary
      - description:
      *openapi.[path].[HTTP method].summary
      - responses. For each response:
         - description
            1. openapi.[path].[HTTP method].response.[HTTP status code]
            2. openapi.[fully qualified class name].[HTTP
            method].response.[HTTP status code]
            3. openapi.[class name].[HTTP method].response.[HTTP status
            code]
            4. openapi.[HTTP method].response.[HTTP status code]
            5. openapi.response.[HTTP status code]


On Fri, Oct 8, 2021 at 7:04 PM Thiago H. de Paula Figueiredo <
thiag...@gmail.com> 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
>


-- 
Thiago

Reply via email to