| <?xml version="1.0"?> | 
 | <!-- | 
 |  | 
 |     Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved. | 
 |  | 
 |     This program and the accompanying materials are made available under the | 
 |     terms of the Eclipse Public License v. 2.0, which is available at | 
 |     http://www.eclipse.org/legal/epl-2.0. | 
 |  | 
 |     This Source Code may also be made available under the following Secondary | 
 |     Licenses when the conditions for such availability set forth in the | 
 |     Eclipse Public License v. 2.0 are satisfied: GNU General Public License, | 
 |     version 2 with the GNU Classpath Exception, which is available at | 
 |     https://www.gnu.org/software/classpath/license.html. | 
 |  | 
 |     SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 | 
 |  | 
 | --> | 
 |  | 
 | <!DOCTYPE chapter [<!ENTITY % ents SYSTEM "jersey.ent" > %ents; ]> | 
 | <chapter xmlns="http://docbook.org/ns/docbook" | 
 |          version="5.0" | 
 |          xml:lang="en" | 
 |          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
 |          xmlns:xi="http://www.w3.org/2001/XInclude" | 
 |          xmlns:xlink="http://www.w3.org/1999/xlink" | 
 |          xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd | 
 |                              http://www.w3.org/1999/xlink http://www.w3.org/1999/xlink.xsd" | 
 |          xml:id="resource-builder"> | 
 |  | 
 |     <title>Programmatic API for Building Resources</title> | 
 |  | 
 |     <section> | 
 |         <title>Introduction</title> | 
 |         <para>A standard approach of developing JAX-RS application is to implement resource classes annotated with &jaxrs.Path; | 
 |             with resource methods annotated with HTTP method annotations like &jaxrs.GET; or &jaxrs.POST; and | 
 |             implement needed functionality. This approach is described in the chapter | 
 |             <link xlink:href="jaxrs-resources.html">JAX-RS Application, Resources and Sub-Resources</link>. Besides this standard | 
 |             JAX-RS approach, Jersey offers an API for constructing resources programmatically. | 
 |             </para> | 
 |  | 
 |         <para> | 
 |             Imagine a situation where a deployed JAX-RS application consists of many resource classes. These resources implement | 
 |             standard HTTP methods like  &jaxrs.GET;, &jaxrs.POST;, &jaxrs.DELETE;. In some situations it would be useful to add | 
 |             an &jaxrs.OPTIONS; method which would return some kind of meta data about the deployed resource. Ideally, you would | 
 |             want to expose the functionality as an additional feature and you want to decide at the deploy time whether you want | 
 |             to add your custom &lit.http.OPTIONS; method. However, when custom &lit.http.OPTIONS; method are not | 
 |             enabled you would like to be &lit.http.OPTIONS; requests handled in the standard way by JAX-RS runtime. To | 
 |             achieve this you would need to modify the code to add or remove custom &lit.http.OPTIONS; methods before | 
 |             deployment. Another way would be to use programmatic API to build resource according to your needs. | 
 |         </para> | 
 |         <para> | 
 |             Another use case of programmatic resource builder API is when you build any generic RESTful interface which | 
 |             depends on lot of configuration parameters or for example database structure. Your resource classes would | 
 |             need to have different methods, different structure for every new application deploy. You could use more solutions | 
 |             including approaches where your resource classes would be built using Java byte code manipulation. | 
 |             However, this is exactly the case when you can solve the problem cleanly with the programmatic resource builder API. | 
 |             Let's have a closer look at how the API can be utilized. | 
 |         </para> | 
 |     </section> | 
 |  | 
 |     <section> | 
 |         <title>Programmatic Hello World example</title> | 
 |         <para> | 
 |             Jersey Programmatic API was designed to fully support JAX-RS resource model. In other words, every resource that can | 
 |             be designed using standard JAX-RS approach via annotated resource classes can be also modelled using Jersey | 
 |             programmatic API. Let's try to build simple hello world resource using standard approach first and | 
 |             then using the Jersey programmatic resource builder API. | 
 |         </para> | 
 |         <para> | 
 |             The following example shows standard JAX-RS "Hello world!" resource class. | 
 |             <example> | 
 |                 <title>A standard resource class</title> | 
 |                 <programlisting language="java" linenumbering="numbered"> | 
 |                     @Path("helloworld") | 
 |                     public class HelloWorldResource { | 
 |  | 
 |                         @GET | 
 |                         @Produces("text/plain") | 
 |                         public String getHello() { | 
 |                             return "Hello World!"; | 
 |                         } | 
 |                     } | 
 |                 </programlisting> | 
 |             </example> | 
 |             This is just a simple resource class with one GET method returning "Hello World!" string that will be serialized | 
 |             as text/plain media type. | 
 |         </para> | 
 |  | 
 |         <para> | 
 |             Now we will design this simple resource using programmatic API. | 
 |             <example> | 
 |                 <title>A programmatic resource</title> | 
 |                 <programlisting language="java" linenumbering="numbered"> | 
 |                     package org.glassfish.jersey.examples.helloworld; | 
 |  | 
 |                     import jakarta.ws.rs.container.ContainerRequestContext; | 
 |                     import jakarta.ws.rs.core.Application; | 
 |                     import jakarta.ws.rs.core.Response; | 
 |                     import org.glassfish.jersey.process.Inflector; | 
 |                     import org.glassfish.jersey.server.ResourceConfig; | 
 |                     import org.glassfish.jersey.server.model.Resource; | 
 |                     import org.glassfish.jersey.server.model.ResourceMethod; | 
 |  | 
 |  | 
 |                     public static class MyResourceConfig extends ResourceConfig { | 
 |  | 
 |                         public MyResourceConfig() { | 
 |                             final Resource.Builder resourceBuilder = Resource.builder(); | 
 |                             resourceBuilder.path("helloworld"); | 
 |  | 
 |                             final ResourceMethod.Builder methodBuilder = resourceBuilder.addMethod("GET"); | 
 |                             methodBuilder.produces(MediaType.TEXT_PLAIN_TYPE) | 
 |                                     .handledBy(new Inflector<ContainerRequestContext, String>() { | 
 |  | 
 |                                 @Override | 
 |                                 public String apply(ContainerRequestContext containerRequestContext) { | 
 |                                     return "Hello World!"; | 
 |                                 } | 
 |                             }); | 
 |  | 
 |                             final Resource resource = resourceBuilder.build(); | 
 |                             registerResources(resource); | 
 |                         } | 
 |                     } | 
 |                 </programlisting> | 
 |             </example> | 
 |             First, focus on the content of the <literal>MyResourceConfig</literal> constructor in the example. | 
 |             The Jersey programmatic resource model is constructed from <literal>Resource</literal>s that contain | 
 |             <literal>ResourceMethod</literal>s. In the example, a single resource would be constructed from a | 
 |             <literal>Resource</literal> containing one &lit.http.GET; resource method that returns "Hello World!". | 
 |             The main entry point for building programmatic resources in Jersey is the | 
 |             <emphasis><literal>Resource.Builder</literal></emphasis> class. <literal>Resource.Builder</literal> contains just | 
 |             a few methods like the <literal>path</literal> method used in the example, which sets the name of the path. Another | 
 |             useful method is a <literal>addMethod(String path)</literal> which adds a new method to the resource builder and | 
 |             returns a resource method builder for the new method. Resource method builder contains methods which | 
 |             set consumed and produced media type, define name bindings, timeout for asynchronous executions, etc. It is always | 
 |             necessary to define a resource method handler (i.e. the code of the resource method that will return "Hello World!"). | 
 |             There are more options how a resource method can be handled. In the example the implementation of | 
 |             <literal>Inflector</literal> is used. The Jersey <literal>Inflector</literal> interface defines a simple contract for | 
 |             transformation of a request into a response. An inflector can either return a &jaxrs.core.Response; or directly | 
 |             an entity object, the way it is shown in the example. Another option is to setup a Java method handler using | 
 |             <literal>handledBy(Class<?> handlerClass, Method method)</literal> and pass it the chosen | 
 |             <literal>java.lang.reflect.Method</literal> instance together with the enclosing class. | 
 |         </para> | 
 |         <para> | 
 |             A resource method model construction can be explicitly completed by invoking <literal>build()</literal> on the | 
 |             resource method builder. It is however not necessary to do so as the new resource method model will be built | 
 |             automatically once the parent resource is built. Once a resource model is built, it is registered | 
 |             into the resource config at the last line of the <literal>MyResourceConfig</literal> constructor in the example. | 
 |         </para> | 
 |  | 
 |         <section> | 
 |             <title>Deployment of programmatic resources</title> | 
 |  | 
 |             <para> | 
 |                 Let's now look at how a programmatic resources are deployed. | 
 |                 The easiest way to setup your application as well as register any programmatic resources in Jersey | 
 |                 is to use a Jersey &lit.jersey.server.ResourceConfig; utility class, an extension of &jaxrs.core.Application; | 
 |                 class. | 
 |                 If you deploy your Jersey application into a Servlet container you will need to provide a &jaxrs.core.Application; | 
 |                 subclass that will be used for configuration. You may use a <literal>web.xml</literal> where you would define a | 
 |                 <literal>org.glassfish.jersey.servlet.ServletContainer</literal> Servlet entry there and specify initial parameter | 
 |                 <literal>jakarta.ws.rs.Application</literal> with the class name of your JAX-RS Application that you | 
 |                 wish to deploy. In the example above, this application will be <literal>MyResourceConfig</literal> class. This is | 
 |                 the reason why <literal>MyResourceConfig</literal> extends the &lit.jersey.server.ResourceConfig; (which, if you | 
 |                 remember extends the <literal>jakarta.ws.rs.Application</literal>). | 
 |             </para> | 
 |             <para> | 
 |                 The following example shows a fragment of <literal>web.xml</literal> that can be used to deploy the | 
 |                 &lit.jersey.server.ResourceConfig; JAX-RS application. | 
 |                 <example> | 
 |                     <title>A programmatic resource</title> | 
 |                     <programlisting language="xml" linenumbering="numbered"> | 
 |                         ... | 
 |                         <servlet> | 
 |                             <servlet-name>org.glassfish.jersey.examples.helloworld.MyApplication</servlet-name> | 
 |                             <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> | 
 |                             <init-param> | 
 |                                 <param-name>jakarta.ws.rs.Application</param-name> | 
 |                                 <param-value>org.glassfish.jersey.examples.helloworld.MyResourceConfig</param-value> | 
 |                             </init-param> | 
 |                             <load-on-startup>1</load-on-startup> | 
 |                         </servlet> | 
 |                         <servlet-mapping> | 
 |                             <servlet-name>org.glassfish.jersey.examples.helloworld.MyApplication</servlet-name> | 
 |                             <url-pattern>/*</url-pattern> | 
 |                         </servlet-mapping> | 
 |                         ... | 
 |                     </programlisting> | 
 |                 </example> | 
 |             </para> | 
 |             <para> | 
 |                 If you use another deployment options and you have accessible instance of ResourceConfig which you use | 
 |                 for configuration, you can register programmatic resources directly by <literal>registerResources()</literal> | 
 |                 method called on the ResourceConfig. Please note that the method registerResources() replaces all the previously | 
 |                 registered resources. | 
 |             </para> | 
 |             <para> | 
 |                 Because Jersey programmatic API is not a standard JAX-RS feature the &lit.jersey.server.ResourceConfig; must be | 
 |                 used to register programmatic resources as shown above. See <link linkend="deployment">deployment chapter</link> | 
 |                 for more information. | 
 |             </para> | 
 |         </section> | 
 |     </section> | 
 |  | 
 |     <section> | 
 |         <title>Additional examples</title> | 
 |         <para> | 
 |             <example> | 
 |                 <title>A programmatic resource</title> | 
 |                 <programlisting language="java" linenumbering="numbered"> | 
 |                     final Resource.Builder resourceBuilder = Resource.builder(HelloWorldResource.class); | 
 |                     resourceBuilder.addMethod("OPTIONS") | 
 |                         .handledBy(new Inflector<ContainerRequestContext, Response>() { | 
 |                             @Override | 
 |                             public Response apply(ContainerRequestContext containerRequestContext) { | 
 |                                 return Response.ok("This is a response to an OPTIONS method.").build(); | 
 |                             } | 
 |                         }); | 
 |                     final Resource resource = resourceBuilder.build(); | 
 |                 </programlisting> | 
 |             </example> | 
 |         </para> | 
 |         <para> | 
 |             In the example above the <literal>Resource</literal> is built from | 
 |             a <literal>HelloWorldResource</literal> resource class. The resource model built this way | 
 |             contains a &lit.http.GET; method producing <literal>'text/plain'</literal> responses with "Hello World!" entity. | 
 |             This is quite important as it allows you to build whatever Resource objects based on introspecting | 
 |             existing JAX-RS resources and use builder API to enhance such these standard resources. | 
 |             In the example we used already implemented <literal>HelloWorldResource</literal> resource class | 
 |             and enhanced it by &lit.http.OPTIONS; method. The &lit.http.OPTIONS; method is handled by an Inflector which | 
 |             returns &jaxrs.core.Response;. | 
 |          </para> | 
 |  | 
 |         <para> | 
 |             The following sample shows how to define sub-resource methods (methods that contains sub-path). | 
 |         </para> | 
 |         <para> | 
 |             <example> | 
 |                 <title>A programmatic resource</title> | 
 |                 <programlisting language="java" linenumbering="numbered"> | 
 |                     final Resource.Builder resourceBuilder = Resource.builder("helloworld"); | 
 |  | 
 |                     final Resource.Builder childResource = resourceBuilder.addChildResource("subresource"); | 
 |                     childResource.addMethod("GET").handledBy(new GetInflector()); | 
 |  | 
 |                     final Resource resource = resourceBuilder.build(); | 
 |                 </programlisting> | 
 |             </example> | 
 |         </para> | 
 |         <para> | 
 |             Sub-resource methods are defined using so called <emphasis>child resource models</emphasis>. Child | 
 |             resource models (or child resources) are programmatic resources build in the same way as any other | 
 |             programmatic resource but they are registered as a child resource of a parent resource. The child resource | 
 |             in the example is build directly from the parent builder using method | 
 |             <literal>addChildResource(String path)</literal>. | 
 |             However, there is also an option to build a child resource model separately as a standard resource and then | 
 |             add it as a child resource to a selected parent resource. This means that child resource objects | 
 |             can be reused to define child resources in different parent resources (you just build a single child resource | 
 |             and then register it in multiple parent resources). Each child resource groups methods with the same sub-resource | 
 |             path. Note that a child resource cannot have any child resources as there is nothing like sub-sub-resource | 
 |             method concept in JAX-RS. For example if a sub resource method contains more path segments in its path | 
 |             (e.g. "/root/sub/resource/method" where "root" is a path of the resource and "sub/resource/method" is the sub | 
 |             resource method path) then parent resource will have path "root" and child resource will have path | 
 |             "sub/resource/method" (so, there will not be any separate nested sub-resources for "sub", "resource" and "method"). | 
 |         </para> | 
 |         <para> | 
 |             See the javadocs of the resource builder API for more information. | 
 |             <link xlink:href="&jersey.javadoc.root.uri;/org/glassfish/jersey/server/model/Resource.Builder.html">Resource.Builder</link> | 
 |         </para> | 
 |     </section> | 
 |     <section> | 
 |         <title>Model processors</title> | 
 |         <para> | 
 |             Jersey gives you an option to register so called <emphasis>model processor providers</emphasis>. These providers | 
 |             are able to modify or enhance the application resource model during application deployment. This is an advanced | 
 |             feature and will not be needed in most use cases. However, imagine you would like to add &lit.http.OPTIONS; resource | 
 |             method to each deployed resource as it is described at the top of this chapter. You would want to do it for every | 
 |             programmatic resource that is registered as well as for all standard JAX-RS resources. | 
 |         </para> | 
 |         <para> | 
 |             To do that, you first need to register a model processor provider in your application, which implements | 
 |             <literal>org.glassfish.jersey.server.model.ModelProcessor</literal> extension contract. An example of | 
 |             a model processor implementation is shown here: | 
 |             <example> | 
 |                 <title>A programmatic resource</title> | 
 |                 <programlisting language="java" linenumbering="numbered"> | 
 |                     import jakarta.ws.rs.GET; | 
 |                     import jakarta.ws.rs.Path; | 
 |                     import jakarta.ws.rs.Produces; | 
 |                     import jakarta.ws.rs.container.ContainerRequestContext; | 
 |                     import jakarta.ws.rs.core.Application; | 
 |                     import jakarta.ws.rs.core.Configuration; | 
 |                     import jakarta.ws.rs.core.MediaType; | 
 |                     import jakarta.ws.rs.core.Response; | 
 |                     import jakarta.ws.rs.ext.Provider; | 
 |  | 
 |                     import org.glassfish.jersey.process.Inflector; | 
 |                     import org.glassfish.jersey.server.model.ModelProcessor; | 
 |                     import org.glassfish.jersey.server.model.Resource; | 
 |                     import org.glassfish.jersey.server.model.ResourceMethod; | 
 |                     import org.glassfish.jersey.server.model.ResourceModel; | 
 |  | 
 |                     @Provider | 
 |                     public static class MyOptionsModelProcessor implements ModelProcessor { | 
 |  | 
 |                         @Override | 
 |                         public ResourceModel processResourceModel(ResourceModel resourceModel, Configuration configuration) { | 
 |                             // we get the resource model and we want to enhance each resource by OPTIONS method | 
 |                             ResourceModel.Builder newResourceModelBuilder = new ResourceModel.Builder(false); | 
 |                             for (final Resource resource : resourceModel.getResources()) { | 
 |                                 // for each resource in the resource model we create a new builder which is based on the old resource | 
 |                                 final Resource.Builder resourceBuilder = Resource.builder(resource); | 
 |  | 
 |                                 // we add a new OPTIONS method to each resource | 
 |                                 // note that we should check whether the method does not yet exist to avoid failures | 
 |                                 resourceBuilder.addMethod("OPTIONS") | 
 |                                     .handledBy(new Inflector<ContainerRequestContext, String>() { | 
 |                                         @Override | 
 |                                         public String apply(ContainerRequestContext containerRequestContext) { | 
 |                                             return "On this path the resource with " + resource.getResourceMethods().size() | 
 |                                                 + " methods is deployed."; | 
 |                                         } | 
 |                                         }).produces(MediaType.TEXT_PLAIN) | 
 |                                           .extended(true); // extended means: not part of core RESTful API | 
 |  | 
 |                                 // we add to the model new resource which is a combination of the old resource enhanced | 
 |                                 // by the OPTIONS method | 
 |                                 newResourceModelBuilder.addResource(resourceBuilder.build()); | 
 |                             } | 
 |  | 
 |                             final ResourceModel newResourceModel = newResourceModelBuilder.build(); | 
 |                             // and we return new model | 
 |                             return newResourceModel; | 
 |                         }; | 
 |  | 
 |                         @Override | 
 |                         public ResourceModel processSubResource(ResourceModel subResourceModel, Configuration configuration) { | 
 |                             // we just return the original subResourceModel which means we do not want to do any modification | 
 |                             return subResourceModel; | 
 |                         } | 
 |                     } | 
 |                 </programlisting> | 
 |             </example> | 
 |             The <literal>MyOptionsModelProcessor</literal> from the example is a relatively simple model processor which | 
 |             iterates over all registered resources and for all of them builds a new resource that is equal to the old resource | 
 |             except it is enhanced with a new &lit.http.OPTIONS; method. | 
 |         </para> | 
 |         <para> | 
 |             Note that you only need to register such a ModelProcessor as your custom extension provider in the same way as you | 
 |             would register any standard JAX-RS extension provider. During an application deployment, Jersey will look for any | 
 |             registered model processor and execute them. As you can see, model processors are very powerful as they can do | 
 |             any manipulations with the resource models. A model processor can even, for example, completely ignore | 
 |             the old resource model and return a new custom resource model with a single "Hello world!" resource, which would | 
 |             result in only the "Hello world!" resource being deployed in your application. Of course, it would not not make | 
 |             much sense to implement such model processor, but the scenario demonstrates how powerful the model processor concept | 
 |             is. A better, real-life use case scenario would, for example, be to always add some custom new resource to each | 
 |             application that might return additional metadata about the deployed application. Or, you might want to | 
 |             filter out particular resources or resource methods, which is another situation where a model processor could | 
 |             be used successfully. | 
 |         </para> | 
 |         <para> | 
 |             Also note that <literal>processSubResource(ResourceModel subResourceModel, Configuration configuration)</literal> | 
 |             method is executed for each sub resource returned from the sub resource locator. The example is simplified and does | 
 |             not do any manipulation but probably in such a case you would want to enhance all sub resources with | 
 |             a new &lit.http.OPTIONS; method handlers too. | 
 |         </para> | 
 |         <para> | 
 |             It is important to remember that any model processor must always return valid resource model. As you might have | 
 |             already noticed, in the example above this important rule is not followed. If any of the resources in the original | 
 |             resource model would already have an &lit.http.OPTIONS; method handler defined, adding another handler would cause | 
 |             the application fail during the deployment in the resource model validation phase. In order to retain the consistency | 
 |             of the final model, a model processor implementation would have to be more robust than what is shown in the example. | 
 |         </para> | 
 |     </section> | 
 | </chapter> |