REpresentational State Transfer (REST) is a simple pattern for
producing Web Services. RESTful services use URI pattern matching to match
a particular web resource. Different HTTP verbs, for example
GET
and DELETE
, map to different operations on
that resource. Standard HTTP response codes are used to communicate the
result of an operation, potentially including a response body if the
operation returns a result.
The [1] Jakarta RESTful Web Services 3.0 Specification defines a set of
annotation mappings which allow Plain Old Java Objects (POJOs) to be
directly exposed as RESTful web resources; these resources can also be
grouped together using a Jakarta RESTful Web Services
Application
. Furthermore the specification defines a plugable
model for extending the behavior of the application and the features of
the Jakarta RESTful Web Services container itself. For example an
extension may define specific error responses that should be sent when
particular exceptions occur, or an extension may add support for
serializing responses to a different format. The OSGi Whiteboard
Specification for Jakarta RESTful Web Services provides a light and
convenient way of using these POJOs, applications and extensions in an
OSGi environment through the use of the [3] Whiteboard Pattern.
The Whiteboard Specification for Jakarta RESTful Web Services supports:
-
Registering Resources - Registering a Jakarta RESTful Web Services annotated POJO in the Service Registry makes it available to be bound to an endpoint and to start responding to incoming requests.
-
Registering Applications - Registering a Jakarta RESTful Web Services
Application
in the Service Registry makes it available to be bound to an endpoint and to start responding to incoming requests. -
Registering Extensions - The Jakarta RESTful Web Services specification defines a variety of plugable extensions. These extensions can be registered in the Service Registry to include them in the handling pipeline.
-
Requiring Extensions - Sometimes Jakarta RESTful Web Services resources, or even Jakarta RESTful Web Services extensions, depend upon the presence of another extension. For example a Jakarta RESTful Web Services resource and exception mapper may both depend on a JSON serializer. Jakarta RESTful Web Services Whiteboard services may define preconditions that must be satisfied before they can be bound.
Jakarta RESTful Web Services Whiteboard implementations must support at least version 3.0 of the Jakarta RESTful Web Services API.
This specification defines the following entities:
-
Jakarta RESTful Web Services Whiteboard service - An object registered in the Service Registry providing the necessary Whiteboard service properties defined by this specification. Whiteboard services may be resource, application or extension services
-
Jakarta RESTful Web Services Whiteboard implementation - An implementation that provides one or more Jakarta RESTful Web Services Whiteboards.
-
Jakarta RESTful Web Services Whiteboard - A runtime instance that processes Jakarta RESTful Web Services Whiteboard services. Each Jakarta RESTful Web Services Whiteboard service may be processed by multiple Jakarta RESTful Web Services Whiteboards. Different Jakarta RESTful Web Services Whiteboards provided by the same Jakarta RESTful Web Services Whiteboard implementation may configured differently, for example using different ports or root contexts.
-
Jakarta RESTful Web Services Service Runtime service - A service providing runtime introspection into a Jakarta RESTful Web Services Whiteboard instance.
-
Jakarta RESTful Web Services Resource Service - A service that provides one or more RESTful resource methods which map to incoming HTTP requests.
-
Jakarta RESTful Web Services Application Service - A service that provides a
jakarta.ws.rs.core.Application
to be hosted by a Jakarta RESTful Web Services Whiteboard. -
Jakarta RESTful Web Services Extension Service - A service that extends the functionality of a Jakarta RESTful Web Services Whiteboard.
-
Static Resources - Jakarta RESTful Web Services resources that are included programmatically in a Jakarta RESTful Web Services Whiteboard application, rather than being added at runtime by the whiteboard.
The Figure 151.1 shows an OSGi framework running a Jakarta RESTful Web Services Whiteboard Implementation bundle. This bundle has been configured to provide two Jakarta RESTful Web Services whiteboards, each of which has a corresponding Jakarta RESTful Web Services Service Runtime Service. The various Jakarta RESTful Web Services Whiteboard services available in the framework are discovered and processed by both whiteboards.
An important principle of the Whiteboard Specification for Jakarta RESTful Web Services is that an OSGi framework may contain many active Jakarta RESTful Web Services Whiteboards at any time, even if there is only a single Jakarta RESTful Web Services Whiteboard implementation present in the framework. In addition to providing a web endpoint with which to register Whiteboard services, a Jakarta RESTful Web Services Whiteboard provides a holder for Jakarta RESTful Web Services Applications.
All Jakarta RESTful Web Services Whiteboards have a
default
application which is used to register resources that
do not target an existing application. In this respect a Jakarta RESTful
Web Services whiteboard application shares some similarities with a
Servlet Context in the Jakarta Servlet Whiteboard. Resources
registered with a Jakarta RESTful Web Services Whiteboard are always
registered as part of an application. The generated name of the default
application is .default
, and it is mapped to the root context
of the Jakarta RESTful Web Services Whiteboard.
A Jakarta RESTful Web Services Whiteboard implementation must create a Jakarta RESTful Web Services Whiteboard instance, however it is expected that most implementations will permit multiple Jakarta RESTful Web Services whiteboards to be configured. These instances may differ significantly, or may simply offer the same capabilities on a different port.
For details on the association process between Jakarta RESTful Web Services Whiteboard services and a Jakarta RESTful Web Services Whiteboard see Common Whiteboard Properties.
The JakartarsServiceRuntime service represents the runtime state information of a Jakarta RESTful Web Services Whiteboard instance. This information is provided through Data Transfer Objects (DTOs). The architecture of OSGi DTOs is described in OSGi Core Release 8.
Each Jakarta RESTful Web Services Whiteboard implementation
registers exactly one JakartarsServiceRuntime
service per
Jakarta RESTful Web Services Whiteboard. The service properties of the
Jakarta RESTful Web Services Service Runtime Service can be used to
target Jakarta RESTful Web Services Whiteboard services at specific
Jakarta RESTful Web Services whiteboards, as described by the
osgi.jakartars.whiteboard.target
property in Common Whiteboard Properties.
The JakartarsServiceRuntime
provides service
registration properties to declare its underlying Jakarta RESTful Web
Services Whiteboard. These service properties can include
implementation-specific key-value pairs. They also include the
following:
Table 151.1 Service properties for the JakartarsServiceRuntime
service
Service Property Name | Type | Description |
---|---|---|
osgi.jakartars.endpoint |
String+ |
Endpoint(s) where this Jakarta RESTful Web
Services Whiteboard is listening. Registered Whiteboard services
are made available here. Values could be provided as URLs e.g.
|
service.changecount |
Long |
Whenever the DTOs available from the Jakarta RESTful Web Services Service Runtime service change, the value of this property will increase. This allows
interested parties to be notified of changes to the DTOs by
observing Service Events of type |
The Jakarta RESTful Web Services Service Runtime service provides information about registered Whiteboard services through the RuntimeDTO.
The Runtime DTO provides information about services that have been successfully registered as well as information about the Jakarta RESTful Web Services Whiteboard services that were not successfully registered. Jakarta RESTful Web Services Whiteboard services that have the required properties set but cannot be processed, are reflected in the failure DTOs. Jakarta RESTful Web Services Whiteboard services of interfaces described in this specification that do not have the required properties set are ignored and not reflected in the failure DTOs.
The Runtime DTO can be obtained using the getRuntimeDTO() method. The Runtime DTO returned provides a snapshot of the state of the Jakarta RESTful Web Services Runtime, including the Jakarta RESTful Web Services Whiteboard resources, extensions and applications that are active in each registered application. The Runtime DTO also includes information about Whiteboard services which could not be activated.
When whiteboard services are registered with the whiteboard they
must be introspected and this information reflected in the DTO(s) for
that service. This introspection will include looking for annotations
such as @GET
and @Path
both at a class and
method level. The values associated with these annotations must then
be appropriately combined, for example when @Path
is
declared on a type and method level, and recorded in the DTO.
There are a variety of reasons that whiteboard services may not be able to be used by the whiteboard. For example, if the whiteboard service cannot be retrieved from the service registry, or if the whiteboard service provides an invalid service property value, such as a malformed filter.
In these cases the failed services are represented in the Runtime DTO under one of the failed DTO properties. Depending upon the failure reason one or more of the properties of the failed DTO may be unavailable. For example if the service cannot be retrieved from the service registry then it cannot be introspected for annotations. A failure DTO will always contain the service id for the failed service and the failure reason. The whiteboard implementation must then fill in other DTO properties on a best effort basis.
Implementations of this specification will often be backed by existing servlet containers, such as the OSGi Http Whiteboard, or a Jakarta EE application server. There may also exist implementations which bridge into a servlet container into which the OSGi Framework has been deployed as a Web Application.
In bridged situations the Jakarta RESTful Web Services Whiteboard implementation will have limited facilities for creating new Jakarta RESTful Web Services whiteboards, and may also have limited information about its environment.
Information about the surrounding Servlet Container, including ServletContext information and HttpSession data, is available to Jakarta RESTful Web Services Whiteboard resources using standard Jakarta RESTful Web Services injection behavior.
@GET
@Path("{name}")
public String interrogateSession(@PathParam("name") String name,
@Context HttpServletRequest req) {
HttpSession s = req.getSession();
return String.valueOf(s.getAttribute(name));
}
A Jakarta RESTful Web Services Whiteboard implementation needs to
ensure that Http Sessions are not shared amongst different Jakarta
RESTful Web Services Whiteboards, or amongst different Jakarta RESTful
Web Services Whiteboard applications. That is,
HttpServletRequest.getSession()
calls must provide
different sessions for each whiteboard application with which a Jakarta
RESTful Web Services whiteboard service is associated.
Even when they are created by the same Jakarta RESTful Web Services Whiteboard implementation, each Jakarta RESTful Web Services Whiteboard instance is separate, and isolated from other instances. Importantly, Jakarta RESTful Web Services Whiteboard services targeted to one Jakarta RESTful Web Services Whiteboard application must not be visible in any other Whiteboard or applications to which they are not targeted.
This isolation restriction is critical, as it ensures that different Jakarta RESTful Web Services Whiteboard applications can be configured with different, potentially overlapping, incompatible extension features.
Jakarta RESTful Web Services Whiteboard services support common service registration properties to associate them with a Jakarta RESTful Web Services Whiteboard. These properties apply to whiteboard resources, extensions and applications except where explicitly stated otherwise. Each service property has an associated Component Property Type annotation that can be used to easily apply the property to a Declarative Services Component.
Table 151.2 Common properties
Service Property | Type | Description |
---|---|---|
|
optional |
A user defined name that can be used to identify a
Jakarta RESTful Web Services whiteboard service. Names must follow
OSGi symbolic name rules, and also must not start with the
prefixes If
no name is defined for a Jakarta RESTful Web Services whiteboard
service then one is generated for it. This generated name will
start with a If a Jakarta RESTful Web Services
service is registered with an illegal name then it is not bound
and this is reflected in the failure DTOs. If two Jakarta RESTful
Web Services services are registered with the same name (even if
they are advertised as different types) then only the first
service in ranking order, as specified in
|
|
optional |
One or more LDAP-style filters to select the Jakarta
RESTful Web Services Application(s) with which this Whiteboard
service should be associated. Any service property of the
Application can be filtered on. If these filters are not defined
then the default Application is used. If multiple filters are
defined then each filter is used to select target applications.
Target applications are selected at most once, even if they match
more than one filter. The default application can also be
specifically targeted using the application name
For example, to select an
Application with name
To select all Applications in the whiteboard provide the following value:
If no matching application exists this is reflected in the failure DTOs. See JAKARTA_RS_APPLICATION_SELECT. † Note that this property is not valid for Jakarta RESTful Web Services Application services. |
|
optional |
A set of LDAP-style filters used to express dependencies on one or more extension services. If a filter is provided then the Jakarta RESTful Web Services Whiteboard attempts to match that filter against the service properties of the Whiteboard runtime, the service properties of the whiteboard application, and each of the extension services currently active in the application. This search may occur in any order. If all of the supplied filters are matched then the whiteboard service is registered into the Jakarta RESTful Web Services Whiteboard application. For example, to require an extension
which provides JSON serialization advertising property name
A more detailed version of this example is available in A Jakarta RESTful Web Services Whiteboard Extension Example If any filter(s) fail to match then this is reflected in the failure DTOs. See JAKARTA_RS_EXTENSION_SELECT. |
|
optional |
The value of this service property is an LDAP-style
filter expression to select the Jakarta RESTful Web Services
Whiteboard(s) to handle this Whiteboard service. The LDAP filter
is used to match JakartarsServiceRuntime services. Each Jakarta RESTful Web
Services Whiteboard exposes exactly one
|
Jakarta RESTful Web Services resources can be registered with the
Jakarta RESTful Web Services Whiteboard by registering them as Whiteboard
services. This means that the resource POJO implementations are registered
in the Service Registry. As Jakarta RESTful Web Services resources are
POJOs they may be registered using any valid service
interface, including Object
. The Jakarta RESTful Web Services
container will then use reflection to discover methods and annotations on
the resource object, just as it would outside of OSGi.
As Jakarta RESTful Web Services resources have no common interface
type they are instead registered with the
osgi.jakartars.resource
service property with a value of
"true"
. This property serves as a marker to the Jakarta
RESTful Web Services whiteboard runtime, indicating that this OSGi service
should be hosted as a Jakarta RESTful Web Services Whiteboard
resource.
Jakarta RESTful Web Services resources use the Path
annotation to bind themselves to particular URIs within the Jakarta
RESTful Web Services container. The path annotation can be applied to
the resource class, and to individual resource methods. For example the
following Jakarta RESTful Web Services resource:
@Path("foo")
public class Foo {
private final List<String> entries =
Arrays.asList("fizz", "buzz", "fizzbuzz");
@GET
public List<String> getFoos() {
return Collections.unmodifiableList(entries);
}
@GET
@Path("{name}")
public String getFoo(@PathParam("name") String name) {
if(entries.contains(name)) {
return "A foo called " + name;
}
throw new IllegalArgumentException(“No foo called “ + name);
}
}
This Jakarta RESTful Web Services resource defines two resource
methods. The Path
annotation applied to the class sets the
base URI for all methods in the resource. The getFoos()
method is therefore bound to the URI foo
. The
Path
annotation on the getFoo()
method makes
this method a sub-resource which captures the next token in the URI.
This method is therefore bound to URIs of the form
foo/buzz
.
When used as an OSGi Jakarta RESTful Web Services Whiteboard
service a Jakarta RESTful Web Services resource follows the same mapping
rules, but the base context(s) it uses are determined by the
Application(s) to which it is mapped. For example, when mapped to the
default application of a whiteboard with endpoint
http://127.0.0.1/
the getFoos()
method would
be available at http://127.0.0.1/foo
.
Resource services bound to a Jakarta RESTful Web Services whiteboard application share a single URI namespace with other resources in the application (including any existing static resources). When Jakarta RESTful Web Services services are bound it is possible that one or more methods on these services will map to the same URI. This situation is permitted by the Jakarta RESTful Web Services specification which defines a detailed selection algorithm.
When clashes occur in the Jakarta RESTful Web Services
whiteboard then resources supplied using the service whiteboard must
be preferred to static resources contained in the application. If two
or more whiteboard resources exist then they must be ordered using
ranking order, as specified in
ServiceReference.compareTo
. Unlike for other services in
the Jakarta RESTful Web Services whiteboard, whiteboard resource
services must not be ordered using their natural ordering. Whiteboard
resource services with the same ranking must be considered equal,
following the normal resource method selection rules defined in the
Jakarta RESTful Web Services specification. As per the Core
specification, whiteboard services with no
service.ranking
property must be treated as having a
ranking of 0
.
A key tenet of Jakarta RESTful Web Services is that all resource objects are stateless. In the Jakarta RESTful Web Services specification resources therefore have one of two scopes, they are either singleton, or request-scoped. Singleton resources are created once, potentially outside the Jakarta RESTful Web Services container, and request-scoped resources are created on-demand for each request, then discarded afterwards.
Typically Jakarta RESTful Web Services developers are encouraged
to write request-scoped resources, as this makes it difficult to
accidentally write stateful components. In OSGi, however, it is more
common to write singleton services. On demand instances of OSGi services
can be created, but only if the service is registered as a
prototype
scope.
The Jakarta RESTful Web Services whiteboard implementation is responsible for managing the mismatch between the OSGi service lifecycle model and the Jakarta RESTful Web Services resource lifecycle model. If the Jakarta RESTful Web Services whiteboard resource is registered as prototype scope then the implementation must treat the resources as request-scoped, creating a new service instance for each request and releasing it when the request completes. Otherwise the Jakarta RESTful Web Services whiteboard service must be registered as a singleton scope resource within the application. Singleton scope whiteboard resources must be released by the Jakarta RESTful Web Services whiteboard when the application with which they have been registered is removed from the whiteboard, even if this is only a temporary situation.
If a failure occurs when getting the resource service this will prevent the service from being used, which is reflected using a failure DTO. In such a case the system treats the resource as unusable.
When multiple Jakarta RESTful Web Services Whiteboard
implementations are present all of them can potentially process the
whiteboard resources. In such situations it can be useful to associate
the servlet with a specific whiteboard by specifying the
osgi.http.whiteboard.target
property on the service.
Jakarta RESTful Web Services resources may have objects injected
into them by the Jakarta RESTful Web Services container. These objects
may be related to an incoming request, for example an HTTP header
value, or part of the container runtime. Injected resources are
annotated with a Jakarta RESTful Web Services annotation, for example
@Context
, and may be injected as method parameters, or as
fields in the object.
If the Jakarta RESTful Web Services injected objects are passed
as method parameters then the resource object may be a singleton. If,
however, the objects are injected into fields by the Jakarta RESTful
Web Services container then the resource should be declared as a
prototype
scope. Jakarta RESTful Web Services Whiteboard
implementations may support field injection for singleton resources,
however this behavior is non portable, and may lead to errors at
runtime when using other implementations.
Request-scoped resources are created on demand for a request and
then discarded afterwards. Critically for OSGi services the Jakarta
RESTful Web Services whiteboard must not release
a prototype scope service until after the
response has completed. If the resource makes use of a Jakarta RESTful
Web Services AsyncResponse
, SseEventSink
or
a StreamingOutput
then this may be some time after the
return of resource method, and potentially on a different
thread.
Jakarta RESTful Web Services whiteboard implementations must therefore take special care not to release request scoped instances until they are completely finished.
Jakarta RESTful Web Services supports asynchronous responses either for single-valued results, or for streams of data.
Single valued results may be provided by the
AsyncResponse
type which is injected into resource
methods using the @Suspended
annotation. If the resource
is request scoped then the resource must not be released until after
the AsyncResponse
has completed.
The following example demonstrates the use of the
AsyncResponse
:
@Component(service = MyResource.class,
scope = ServiceScope.PROTOTYPE)
@JakartarsResource
public class MyResource {
@Path(“foo”)
@GET
public void getFoo(@Suspended AsyncResponse async) {
Promise<String> p = doLongRunningTaskAsynchronously();
p.onSuccess(v -> async.resume(v))
.onFailure(t -> async.resume(t));
}
}
Single valued asynchronous results can also be provided by
returning a suitable type from the resource method. This can be a
CompletionStage
as described in the Jakarta RESTful Web
Services specification, or an OSGi Promise
type. In this
case the response from the resource method will be sent once the
returned type has completed, either successfully or by failing.
The following example demonstrates the use of an asynchronous return value:
@Component(service = MyResource.class,
scope = ServiceScope.PROTOTYPE)
@JakartarsResource
public class MyResource {
@Path(“foo”)
@GET
public Promise<String> getFoo() {
Promise<String> p = doLongRunningTaskAsynchronously();
return p;
}
}
Multi-valued results in Jakarta RESTful Web Services are handled
using Server Sent Events. To send Server Sent Events a Jakarta RESTful
Web Services resource must declare its produced media type
appropriately, and inject its resource method with a
SseEventSink
. The resource must also gain access to a
Sse
to use as a factory for Outbound Server Sent Events.
If the resource is request scoped then the resource must not be
released until after the SseEvent
has closed.
The following example demonstrates the use of the Server Sent Events:
@Component(service = MyResource.class,
scope = ServiceScope.PROTOTYPE)
@JakartarsResource
public class MyResource {
@Context
Sse sse;
@GET
@Produces(MediaType.SERVER_SENT_EVENTS)
public void getFoo(@Context SseEventSink sink) {
PushStream<String> p = getStreamOfMessages();
p.map(sse::newEvent)
.forEach(e -> sink::send)
.onResolve(sink::close);
}
}
The following table describes the properties that can be used by Jakarta RESTful Web Services resources registered as Whiteboard services. Additionally, the common properties listed in Table 151.2 on page are supported.
Table 151.3 Service properties for Jakarta RESTful Web Services Whiteboard resource services.
Service Property | Type | Description |
---|---|---|
|
required |
Declares that this service must be processed by the
Jakarta RESTful Web Services whiteboard when set to
|
The following example code uses Declarative Services annotations to register a Jakarta RESTful Web Services Whiteboard service.
@Component(service = MyResource.class,
scope = ServiceScope.PROTOTYPE)
@JakartarsResource
public class MyResource {
@GET
@Path("hello")
@Produces("text/plain")
public String sayHello(){
return "Hello World!";
}
}
This example registers the resource method at:
/hello
. Requests for http://www.acme.com/hello
map to the resource method, which is called to process the
request.
To associate the above example resource with another application add the following service property:
osgi.jakartars.application.select=(osgi.jakartars.name=myApp)
This can also be added using the property annotation:
@JakartarsApplicationSelect("(osgi.jakartars.name=myApp)")
Setting this property requires a Jakarta RESTful Web Services
application named myApp
to be registered:
@Component(service=Application.class)
@JakartarsName("myApp")
@JakartarsApplicationBase("foo")
public class MyApplication extends Application {}
Now the whiteboard resource will be available at
http://www.acme.com/foo/hello
as configured by the custom
Jakarta RESTful Web Services application.
Jakarta RESTful Web Services extensions can be registered with the
Jakarta RESTful Web Services Whiteboard by registering them as Whiteboard
services. This means that the extension implementations are registered in
the Service Registry. It is relatively common for a single extension type
to provide more than one extension interface, for example
MessageBodyReader
and MessageBodyWriter
are
often provided by a single object.
Extension services must be registered with the Jakarta RESTful Web
Services application that they target using only the interfaces that they
advertise in the OSGi service registry. If, for example, an extension
service object implements MessageBodyReader
and
ContainerRequestFilter
but only advertises
MessageBodyReader
in its service registration then it must
only be used as a MessageBodyReader
The following Jakarta RESTful Web Services extension interfaces are supported by this specification:
-
ContainerRequestFilter
andContainerResponseFilter
- these extensions are used to alter the HTTP request and response parameters. -
ReaderInterceptor
andWriterInterceptor
- these extensions are used to alter the incoming or outgoing objects for the call. -
MessageBodyReader
andMessageBodyWriter
- these extensions are used to deserialize/serialize objects to the wire for a given media type, for exampleapplication/json
. -
ContextResolver
extensions are used to provide objects for injection into other Jakarta RESTful Web Services resources and extensions. -
ExceptionMapper
extensions are used to map exceptions thrown by Jakarta RESTful Web Services resources into responses. -
ParamConverterProvider
extensions are used to map rich parameter types to and from String values. -
Feature
andDynamicFeature
- these extensions are used as a way to register multiple extension types with the Jakarta RESTful Web Services container. Dynamic Features further allow the extensions to be targeted to specific resources within the Jakarta RESTful Web Services container.
As Jakarta RESTful Web Services extensions have many possible
interface types, none of which are defined by this specification, they
must be registered with the osgi.jakartars.extension
service
property with a value of true
. This property serves as a
marker to the Jakarta RESTful Web Services whiteboard runtime, indicating
that this OSGi service should be used as a Jakarta RESTful Web Services
Whiteboard extension.
If the osgi.jakartars.extension
is added to a service
which does not advertise any of the Jakarta RESTful Web Services extension
types then this is an error, and must result in a failure DTO being
created.
By default Jakarta RESTful Web Services extensions are applied to
every request, however sometimes they are only needed for a subset of
resource methods. In this case a NameBinding
annotation can
be used to apply the extension to a subset of resource methods. The
following example declares a binding annotation called
FizzBuzz
and uses it to bind an extension which replaces
occurrences of "fizz" with "fizzbuzz".
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@NameBinding
public @interface FizzBuzz{}
@Component
@JakartarsExtension
@FizzBuzz
public class FizzBuzzReplacer implements WriterInterceptor {
public void aroundWriteTo(WriterInterceptorContext ctx) {
Object entity = ctx.getEntity();
if(entity != null) {
ctx.setEntity(entity.toString()
.replace("fizz", "fizzbuzz"));
}
ctx.proceed();
}
}
@Component(service=FizzResource.class)
@JakartarsResource
@Path("fizzbuzz")
public class FizzResource {
@GET
@FizzBuzz
public String getFoos() {
return "fizz, buzz, fizzbuzz";
}
}
The result of an http request to the fizzbuzz
URI
will be fizzbuzz, buzz, fizzbuzzbuzz
The Jakarta RESTful Web Services whiteboard implementation must
support the use of NameBinding
to limit the scope of
applied whiteboard extensions.
Jakarta RESTful Web Services filters can be annotated with
@PreMatching
to indicate that they should be applied before
the Jakarta RESTful Web Services container works out which resource
should be called by the incoming request. These filters can therefore
change the request such that it maps to a different resource than it
would have before the filter’s operation. Pre-matching filters cannot
use NameBinding
as no corresponding named resource is
available to the runtime when they operate.
When used in the OSGi Jakarta RESTful Web Services Whiteboard
Jakarta RESTful Web Services extensions follow the same ordering rules
as defined by the Jakarta RESTful Web Services specification. Where more
than one extension of a particular type is available then they are
ordered according to their jakarta.annotation.Priority
. If
two extensions of the same type have the same priority then the
whiteboard implementation must break the tie by ordering the extensions
according to the natural ordering of their service references, as
specified in ServiceReference.compareTo
, with static
extensions being ranked below all whiteboard services.
The extension processing flow is as follows:
-
Server receives a request
-
Pre-matching
ContainerRequestFilter
s are executed. Changes made here can affect which resource method is chosen -
The Server matches the request to a resource method
-
Post-matching ContainerRequestFilters are executed. This includes execution of all filters which match the incoming path and any name-bound filters.
-
ReaderInterceptors which match the incoming path are applied to the incoming request body. If the request has no body then the ReaderInterceptors are not called.
-
The list of
MessageBodyReader
s applicable to the path and incoming content type are tried according to the standard ordering rules. The firstMessageBodyReader
which states that it can deserialize the entity “wins” and is used to create the entity object. If the incoming request has no body then noMessageBodyReader
s are called. -
If the resource is request scoped then it is instantiated and injected with relevant types from any defined
ContextResolver
s. These are queried in order for each of the injectable fields. -
The resource method is executed, passing any injected parameters from the request, and from any
ContextResolver
s. These are queried in turn for each of the injectable parameters. -
ContainerResponseFilter
s are executed passing the method's response when it is complete. This includes execution of all filters, in order, which match the incoming path and any name-bound filters. Note that if anAsyncResponse
is used then the response may not complete on the same thread as the incoming request. -
WriterInterceptor
s which match the incoming path are applied to the outgoing response stream. If the response has no body then the WriterInterceptors are not called. -
The list of
MessageBodyWriter
s applicable to the path and outgoing content type are tried according to the standard ordering rules. The first writer which states that it can serialize the entity “wins” and is used to write out the entity object. If there is no response body then no writers are called. -
The Server response is flushed and committed. If the resource that created the response was request scoped then it must only be released once the response is complete. Note that this may be at some point in the future, and on a different thread if the resource is using an
AsyncResponse
The osgi.jakartars.extension.select
property
described in Common Whiteboard Properties
applies to extensions as well as Jakarta RESTful Web Services resources.
This is because one extension may depend on another.
The most common reason for an extension to have a dependency is
for a context injection dependency. Dependencies are often provided by a
ContextResolver
so that they can be injected into another
extension. The following example demonstrates a simple dependency on a
Jackson ObjectMapper.
@JakartarsExtension
@JakartarsName("configProvider")
@Component
public class ConfigProvider implements ContextResolver {
private ObjectMapper mapper = new ObjectMapper();
public <T> getContext(Class<T> clazz) {
if(ObjectMapper.class.equals(clazz)) {
return mapper;
}
return null;
}
}
@JakartarsExtension
@JakartarsExtensionSelect("(osgi.jakartars.name=configProvider)")
@Component(scope=ServiceScope.PROTOTYPE)
public class ConfiguredExtension implements WriterInterceptor {
@Context
private Providers providers;
public void aroundWriteTo(WriterInterceptorContext ctx) {
Object entity = ctx.getEntity();
if(entity != null) {
ObjectMapper mapper = providers
.getContextResolver(ObjectMapper.class)
.getContext(ObjectMapper.class);
ctx.setEntity(mapper.writeValueAsString(entity));
}
ctx.proceed();
}
}
Depending on the capabilities of the Jakarta RESTful Web Services whiteboard implementation, and any statically defined extensions that make up a Jakarta RESTful Web Services Whiteboard application, there may be numerous non standard extensions available. These extensions must be represented using service properties on the Jakarta RESTful Web Services Service Runtime, or the whiteboard application as appropriate. This is why the extension select filters must also be matched against the Jakarta RESTful Web Services Service Runtime service and the whiteboard application being targeted.
Jakarta RESTful Web Services extensions have a different lifecycle from Jakarta RESTful Web Services resources, within a single application a Jakarta RESTful Web Services extension always behaves as a singleton. If a Jakarta RESTful Web Services whiteboard extension is registered as prototype scope then the whiteboard implementation must obtain a separate instance for every application to which the extension is applied. Whiteboard extension services must be released by the Jakarta RESTful Web Services whiteboard when the application with which they have been registered is removed from the whiteboard, even if this is only a temporary situation.
Jakarta RESTful Web Services extensions often require
configuration, and need to be configured differently for different
applications. This configuration is typically provided by a Jakarta
RESTful Web Services ContextResolver
and injected into
fields of the extension by the Jakarta RESTful Web Services container.
It is therefore highly recommended that Jakarta RESTful Web Services
Whiteboard extensions are always registered as prototype scope, so that
separate instances can be created for each whiteboard
application.
If an extension is registered as a singleton service then it should not rely on any fields being injected by the Jakarta RESTful Web Services Whiteboard implementation. Jakarta RESTful Web Services Whiteboard implementations may support field injection for singleton extensions, however this behavior is non portable, and may lead to errors at runtime when using other implementations.
The following table describes the properties that can be used by Jakarta RESTful Web Services extensions registered as Whiteboard services. Additionally, the common properties listed in Table 151.2 on page are supported.
Table 151.4 Service properties for Jakarta RESTful Web Services Whiteboard extension services.
Service Property | Type | Description |
---|---|---|
|
required |
Declares that this service must be processed by the
Jakarta RESTful Web Services whiteboard when set to
|
The following example code uses Declarative Services annotations to register a require Jakarta RESTful Web Services Whiteboard extension which provides JSON support, and requires the extension from a Jakarta RESTful Web Services whiteboard resource.
@Component(property="serialize.to=JSON")
@JakartarsExtension
public class JsonProvider implements MessageBodyReader,
MessageBodyWriter {
...
}
@Component(service = Object.class,
scope = ServiceScope.PROTOTYPE)
@JakartarsResource
@JakartarsExtensionSelect("(serialize.to=JSON)")
public class MyResource {
@GET
@Path("hello")
@Produces(MediaType.APPLICATION_JSON)
public List<String> getList(){
return Arrays.asList("Hello", "World!");
}
}
The Jakarta RESTful Web Services specification defines the concept
of an Application
. An application is an object which collects
together one or more Jakarta RESTful Web Services resources and
extensions, and provides them to the Jakarta RESTful Web Services
container. These resources may be provided as pre-instantiated singletons,
or as Class
objects to be reflectively instantiated.
The OSGi Jakarta RESTful Web Services whiteboard supports direct registration of Applications for two reasons:
-
To support the use of legacy Jakarta RESTful Web Services applications with the whiteboard
-
To provide simple scoping of Jakarta RESTful Web Services resources and extensions within a whiteboard, in this scenario it can be desirable to register an otherwise empty Application. This application can then be targeted by whiteboard services using the
osgi.jakartars.application.select
property.
Application
s can be registered with the Jakarta RESTful
Web Services Whiteboard by registering them as Whiteboard services which
advertise themselves using the Jakarta RESTful Web Services
Application
type. In addition the whiteboard services must
provide a osgi.jakartars.application.base
property. The value
of this property is the URI path relative to the root whiteboard context
at which the application will be registered. Note that the value of any
ApplicationPath
annotation will be applied by the container
in addition to the osgi.jakartars.application.base
.
Each registered Whiteboard Application service is provided as a separate application within the whiteboard, and is isolated from other applications, including the default application. Whiteboard applications may be empty, may include zero or more static resources, and may include zero or more static extensions.
The base URI for each application within the whiteboard must be
unique. If two or more applications targeting the same whiteboard are
registered with the same base URI then only the first in ranking order,
as specified in ServiceReference.compareTo
, will be made
available. All other application services with that URI will have a
failure DTO created for them. The same rules also apply to the
osgi.jakartars.name
property, with the highest ranked
service shadowing other applications with the same name.
The default application is implicitly created by the whiteboard
and has the name .default
. The default application has a
lower ranking than all registered services. Therefore an application
registered with a base of /
will shadow a default
application bound at /
.
A whiteboard application service may set an
osgi.jakartars.name
of .default
to replace the
default application. This technique may be used to rebind the default
application to a base uri other than /
.
If a whiteboard application fails (for example if the service get
fails), or cannot be immediately deployed (for example if it has an
unsatisfied osgi.jakartars.extension.select
) then any
applications that it shadows are still shadowed and relevant failure
DTOs are created for all of the applications.
It is possible for an application to require additional whiteboard
extensions before it is eligible to be hosted by the whiteboard. When
making this determination the Whiteboard implementation must perform a
dry-run validation of the osgi.jakartars.extension.select
filter, applying all of the whiteboard extensions targeted to the
application before determining whether the application's requirements
are met.
The following table describes the properties that can be used by
Jakarta RESTful Web Services applications registered as Whiteboard
services. Additionally, the common properties listed in Table 151.2 on page are supported, except for the
osgi.jakartars.application.select
property.
Table 151.5 Service properties for Jakarta RESTful Web Services Whiteboard application services.
Service Property | Type | Description |
---|---|---|
|
required |
Declares that this service must be processed by the Jakarta RESTful Web Services whiteboard, and defines the URI, relative to the root context of the whiteboard, at which the Application should be registered. See JAKARTA_RS_APPLICATION_BASE. |
In Jakarta RESTful Web Services the @Context
annotation may be used to inject the Application
instance
into a resource or extension. Application configuration properties can
also be injected using the Configuration
type.
When using the Jakarta RESTful Web Services Whiteboard it can also
be necessary to access the service properties associated with the
application hosting the resource, for example to allow customization of
the resource's response. To this end, the Jakarta RESTful Web Services
whiteboard implementation must make the Application service properties
available as a Map
in the configuration. The key used to
store this map is
osgi.jakartars.application.serviceProperties
, and it can be
found in any injected Configuration
instance.
Furthermore, for Feature
and
DynamicFeature
extensions the application service
properties must be visible in the FeatureContext
passed to
the extension when applying it to the application. The
FeatureContext
interface provides programmatic access to
the Configuration
for the application, so this visibility
is achieved in the same manner as for an injected Configuration
instance.
In the case where the hosting application is not an OSGi service,
for example a Whiteboard implementation may choose to provide its
default application as an internal detail, then the
osgi.jakartars.application.serviceProperties
map must exist
containing the osgi.jakartars.name
of the application and
the service properties associated with the JakartarsServiceRuntime
service.
The following example code uses Declarative Services annotations to register a Jakarta RESTful Web Services Whiteboard application, and shows how to target an additional whiteboard resource to that application.
@Component(service=Application.class)
@JakartarsApplicationBase("example")
@JakartarsName("myApp")
public class MyApplication extends Application {
public Set<Class<?>> getClasses() {
return new HashSet<>(Arrays.asList(StaticResource.class));
}
}
@Component(service = MyResource.class,
scope = ServiceScope.PROTOTYPE)
@JakartarsResource
@JakartarsApplicationSelect("(osgi.jakartars.name=myApp)")
public class MyResource {
@GET
@Path("hello")
@Produces("text/plain")
public List<String> getList(){
return Arrays.asList("Hello", "World!");
}
}
The MyResource
service will be available at
http://www.acme.com/example/hello
There are a number of error cases where the Jakarta RESTful Web Services whiteboard may be unable to correctly register a resource. All of these cases must result in a failure DTO being created with the appropriate error code.
-
Failure to obtain a service instance - In the case where a published service is unable to be obtained by the Jakarta RESTful Web Services whiteboard then the service is deny listed by the container. A failure DTO is made available from the JakartarsServiceRuntime representing the deny listed service object.
-
Invalid service objects - Jakarta RESTful Web Services extension and Application objects are required to advertise certain interfaces, or to extend certain types. If a service advertises itself using a Jakarta RESTful Web Services whiteboard service property, but fails to advertise an appropriate Jakarta RESTful Web Services type, or fails to provide any resource methods then this is an error and the service must be deny listed by the container. A failure DTO is available from the JakartarsServiceRuntime representing the deny listed service object.
-
Overlapping Application mappings - As with resources in a single application it is possible that two Jakarta RESTful Web Services resources will register for the same path across applications. In this case the application with the longer base URI is shadowed, and a failure DTO is available from the JakartarsServiceRuntime representing the shadowed Application. Note that determining when two Jakarta RESTful Web Services applications overlap requires an analysis of the resource paths and all of sub-resource paths. If any of these paths clash then the entirety of the shadowed application must be unregistered and marked as a failure. It is an implementation error for some application resource paths to be available while others are shadowed.
-
Class-Space Compatibility - Much of the Jakarta RESTful Web Services mapping definition is handled using annotations with runtime visibility. As Jakarta RESTful Web Services beans are POJOs there is no guarantee of class-space compatibility when the Jakarta RESTful Web Services implementation searches for whiteboard services. The Jakarta RESTful Web Services whiteboard must therefore confirm that the registered service shares the correct view of the Jakarta RESTful Web Services packages. If the class space is not consistent then the Jakarta RESTful Web Services whiteboard container must not register the services, but instead should create a failure DTO indicating that the Jakarta RESTful Web Services object is unable to be registered due to an incompatible class-space.
-
Missing Required Extensions - If a Jakarta RESTful Web Services resource or extension requires one or more extensions using a
osgi.jakartars.extension.select
filter then at any given time it is possible that the Jakarta RESTful Web Services container will not be able to host the resource. At this time a failure DTO must be created for the relevant resource or extension service.
The Jakarta RESTful Web Services specification includes a client API
for making REST requests. The normal mechanism for obtaining a
Client
is to use a ClientBuilder
, which is
instantiated using a static factory method. Static factory methods require
the reflective loading of classes and suffer from significant lifecycle
issues, as there is no way to force indirectly wired objects to be
discarded if the implementation bundle is stopped or uninstalled.
Jakarta RESTful Web Services implementations must therefore register their ClientBuilder implementations as OSGi services for bundles to use in making Client instances. The ClientBuilder must be registered as a prototype scoped service. This allows bundles to configure multiple separate Client instances, and ensures that separate bundles will never accidentally provide conflicting configuration to the same ClientBuilder instance.
While Container extensions can be made available using whiteboard services, the same is not true for Clients. There are two main reasons for this:
-
There is no simple way to scope the filters and interceptors that would be applied to a given client. In a multi-tenant environment this could lead to unexpected behaviors.
-
Clients are not, in general, expected to be extended by third parties. The Client model is designed to be used by a bundle when making requests from a REST API. If further requests need to be made by a different bundle then it should create and configure a separate client. This is different from the whiteboard server, where one container port may host several distinct sets of resources.
In order to add filters, interceptors, readers and writers to the
Jakarta RESTful Web Services client users should use the
ClientBuilder#register()
method when building their
client.
The Jakarta RESTful Web Services client API supports both
synchronous and asynchronous calls. In Jakarta RESTful Web Services 2.1
the asynchronous behavior of the client was extended using the
RxInvoker
(reactive invoker) interface. All clients are
required to support a reactive invoker which returns CompletionStage
instances, however in OSGi the common representation of an asynchronous
return is the Promise
. This specification therefore
provides the PromiseRxInvoker interface which can be used to obtain Promises
from the Jakarta RESTful Web Services client.
It is the responsibility of the Jakarta RESTful Web Services
whiteboard implementation to create instances of
PromiseRxInvoker
. The exact mechanism by which instances
are created is undefined, however it is possible to register a portable
factory to create PromiseRxInvoker
instances by
implementing the RxInvokerProvider
interface and
registering this type with the Jakarta RESTful Web Services client. This
portable implementation, however, is forced to use a blocking model by
the underlying Jakarta RESTful Web Services API, and so implementations
may choose to implement a more optimized non-blocking model using
internal types.
Clients of this specification may make use of the
PromiseRxInvoker
using normal Jakarta RESTful Web Services
idioms. For example:
Client client = clientBuilder.build();
Promise<String> p = client.target(REST_SERVICE_URL)
.path("/foo")
.path("/{name}")
.resolveTemplate("name", buzz)
.request()
.rx(PromiseRxInvoker.class)
.get(String.class);
In Jakarta RESTful Web Services 2.1 support was added for Server
Sent Events. These events are consumed by a REST client using the
SseEventSource
. The SseEventSource
is not
created by a Jakarta RESTful Web Services client instance, but is
normally created using a static factory method, which does not work in a
modular environment. Therefore the Jakarta RESTful Web Services
whiteboard implementation must register a
SseEventSourceFactory
service in the service registry. This
object serves as a factory for the Jakarta RESTful Web Services SSE
types.
Note that the SseEventSource has no way to register filters or
message body processors. All of the filters and necessary processors
must be registered with the Jakarta RESTful Web Services client that is
used to create the WebTarget
used when building the
SseEventSource. A client may therefore consume Server Sent Events in the
following way:
Client client = clientBuilder.build();
WebTarget target = client.target(REST_SERVICE_URL)
.path("/foo")
.path("/{name}")
.resolveTemplate("name", buzz);
SseEventSource source = sseFactory.newSource(target);
source.register(event -> doSomething(event));
source.open();
A SseEventSource
may easily be converted into a
PushEventSource
(and consequently a
PushStream
) as follows. Note that the implementation does
not respond to back-pressure requests and should typically be used with
a buffer.
SseEventSource source = sseBuilder.newSource(target);
PushEventSource<InboundSseEvent> pes = pec ->
source.register(e -> {
try {
if(pec.accept(PushEvent.data(e)) < 0) {
source.close();
}
} catch (Exception e) {
try {
pec.accept(PushEvent.error(e));
} finally {
source.close();
}
}
},
t -> pec.accept(PushEvent.error(t)),
() -> pec.accept(PushEvent.close()));
source.open();
return source;
};
The extensions defined by the Jakarta RESTful Web Services
specification make Jakarta RESTful Web Services runtimes highly plugable,
and it is common to extend the behavior of an application using this
model. In many cases the custom behaviors are specific to a particular use
case, for example mapping a specific exception into a
Response
, and there is no need for portability. In some
common cases, however, there are extensions that can be used across a
great many applications.
In order to ensure that a Jakarta RESTful Web Services whiteboard application can make use of a common extension service in a portable way this specification defines standard service property names that should be registered, as appropriate, by whiteboard extension services, whiteboard applications with static extensions, and Jakarta RESTful Web Services whiteboard implementations that provide built-in extension capabilities.
A common use of the Jakarta RESTful Web Services extension
mechanism is to provide support for additional media types, both for
consuming incoming requests and for producing responses. All Jakarta
RESTful Web Services whiteboards must implicitly support
text/plain
and application/xml
(using JAXB),
however commonly used media types, such as application/json
must be provided as an extension.
To ensure that whiteboard resources can depend on support for a
particular media type in a portable way this specification defines the
osgi.jakartars.media.type
property. This property key
should be registered with one or more media types that are supported,
and may be provided by:
-
A Whiteboard extension - if the extension provides general purpose support for reading from and writing to a media type then it should register this property.
-
A Whiteboard application - if the application provides general purpose support for reading from and writing to a media type using a static extension then it should register this property.
-
A Jakarta RESTful Web Services Whiteboard implementation - if the implementation provides general purpose built-in support for reading from and writing to a media type then it should register this property. If the built-in extension is always available then it should also be advertised by the osgi.service Capability for the JakartarsServiceRuntime.
The term general purpose is used to indicate that the media type support must not require implementation specific mapping metadata (for example annotations) and should, at a minimum, work with the OSGi scalar types and DTOs. The property key is available as a constant in JAKARTA_RS_MEDIA_TYPE.
Where possible the value(s) of the
osgi.jakartars.media.type
property should use the IANA
registered names of the media type(s) supported, for example
application/json
. Officially registered media types are
available from [4] IANA Media Type Registrations.
If there is no officially registered media type then a vendor type
should be used. Personal types may also be used, however due to the
lack of portability afforded by personal types it is recommended that
a non-standard property key is used for personal types.
Wildcard types (containing a *
) are often used by
extensions to indicate that they can create a variety of different
media types. Rarely this is because the extension can serialize into
multiple different formats. More typically this is because the
extension can serialize into a format which has multiple names, or
multiple formats which use the same basic serialization. Suffixes can
further modify this behavior, for example VCards may be serialized as
XML using application/vcard+xml
or as JSON using
application/vcard+json
.
Wildcard types must not be used as values for the
osgi.jakartars.media.type
property as these do not
provide sufficient information for whiteboard resources to reliably
select a media type provider. Where a provider wishes to advertise
support for a general suffix, for example +json
or
+cbor
then the provider must advertise the primary media
type associated with the suffix; in the supplied example these would
be application/json
and application/cbor
.
Clients wishing to use suffixed types should therefore also depend on
the primary media type, not the suffixed type, if they wish to be
portable. Where greater specificity is required it is recommended that
the extension be selected based on additional custom properties. This
should also be used for suffixes that have no primary type, for
example +der
. Official media type registrations are
available from [5] IANA Media Type Suffix Registrations
The most commonly required media type for Jakarta RESTful Web
Services services is application/json
. To this end this
specification defines a Component Property annotation JSONRequired which can be applied to a Declarative Services
component to express:
-
An extension requirement for runtime
application/json
media type support -
A requirement for the Jakarta RESTful Web Services whiteboard
-
An optional active time requirement for
application/json
media type support, for use in application resolution/assembly.
Custom third-party annotations can easily be created to support additional media types as necessary, and are used as follows:
@Component(service = MyResource.class,
scope = ServiceScope.PROTOTYPE)
@JakartarsResource
@JSONRequired
@Produces(MediaType.APPLICATION_JSON)
public class MyResource {
@Path(“foo”)
@GET
public List<String> getFoos() {
return Arrays.asList("foo", "bar", "baz");
}
}
A corresponding component property type (JakartarsMediaType) exists for use on a Jakarta RESTful Web Services whiteboard extension or application service which provides media type support. This can be used to declare that one or more media types are supported.
@Component(scope = ServiceScope.PROTOTYPE)
@JakartarsExtension
@JakartarsMediaType(MediaType.APPLICATION_JSON)
public class MyFeature implements Feature {
public boolean configure(FeatureContext context) {
context.register(MyJSONCodec.class);
return true;
}
}
The Jakarta RESTful Web Services Whiteboard implementation bundle
must provide the osgi.implementation
capability with name osgi.jakartars
. This capability can be
used by provisioning tools and during resolution to ensure that a
Jakarta RESTful Web Services Whiteboard implementation is present to
process the Whiteboard services defined in this specification. The
capability must also declare a uses constraint for the
jakarta.ws.rs.*
specification packages, and for the and
OSGi Jakarta RESTful Web Services Whiteboard package. The version of
this capability must match the version of this specification:
Provide-Capability: osgi.implementation;
osgi.implementation="osgi.jakartars";
uses:="jakarta.ws.rs, jakarta.ws.rs.client, jakarta.ws.rs.container,
jakarta.ws.rs.core, jakarta.ws.rs.ext, jakarta.ws.rs.sse,
org.osgi.service.jakartars.whiteboard";
version:Version="2.0"
This capability must follow the rules defined for the osgi.implementation Namespace.
The Jakarta RESTful Web Services Whiteboard implementation must
provide a capability in the osgi.contract
namespace with the name JakartaRESTfulWebServices
if it
exports the Jakarta RESTful Web Services specification packages. See
[5] Portable Java Contract Definitions.
Providing the osgi.contract
capability enables
developer to build portable bundles for packages that are not versioned
under OSGi Semantic Versioning rules. For more details see osgi.contract Namespace.
If the Jakarta RESTful Web Services API is provided by another bundle, the Jakarta RESTful Web Services Whiteboard implementation must be a consumer of the API and require the contract.
The bundle providing the JakartarsServiceRuntime service must provide a capability in the osgi.service
namespace representing this service. This capability must also declare a
uses constraint for the org.osgi.service.jakartars.runtime
and org.osgi.service.jakartars.runtime.dto
packages:
Provide-Capability: osgi.service;
objectClass:List<String>=
"org.osgi.service.jakartars.runtime.JakartarsServiceRuntime";
uses:="org.osgi.service.jakartars.runtime,
org.osgi.service.jakartars.runtime.dto"
The bundle providing the
jakarta.ws.rs.client.ClientBuilder
service must also
provide a capability in the osgi.service
namespace representing this service. This capability must declare that
the service is prototype scope, and that there is a uses constraint for
the jakarta.ws.rs.client
package:
Provide-Capability: osgi.service;
objectClass:List<String>="jakarta.ws.rs.client.ClientBuilder";
uses:="jakarta.ws.rs.client,org.osgi.service.jakartars.client";
service.scope="prototype"
The bundle providing the
org.osgi.service.jakartars.client.SseEventSourceFactory
service must also provide a capability in the osgi.service
namespace representing this service. This capability must declare a uses
constraint for the org.osgi.service.jakartars.client
package:
Provide-Capability: osgi.service;
objectClass:List<String>=
"org.osgi.service.jakartars.client.SseEventSourceFactory";
uses:="org.osgi.service.jakartars.client"
These capabilities must follow the rules defined for the osgi.service Namespace.
This section only applies when executing in an OSGi environment which is enforcing Java permissions.
Bundles that need to register Jakarta RESTful Web Services
Whiteboard services must be granted
ServicePermission[interfaceName, REGISTER]
where interface
name is the relevant Jakarta RESTful Web Services Whiteboard service
interface name.
The Http Whiteboard implementation must be granted
ServicePermission[*, GET]
to retrieve the Jakarta RESTful
Web Services Whiteboard services from the service registry.
Bundles that need to introspect the state of the Jakarta RESTful
Web Services runtime will need
ServicePermission[org.osgi.service.jakartars.runtime.JakartarsServiceRuntime,
GET]
to obtain the Jakarta RESTful Web Services Service Runtime
service and access the DTO types.
This specification does not require that the Jakarta RESTful Web
Services Whiteboard implementation is granted All Permission or wraps
calls to the Jakarta RESTful Web Services Whiteboard services in a
doPrivileged
block. Therefore, it is the responsibility of
the Jakarta RESTful Web Services Whiteboard services to use a
doPrivileged
block when performing privileged
operations.
Jakarta RESTful Web Services Whiteboard Client Package Version 1.0.
Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest. This package has two types of users: the consumers that use the API in this package and the providers that implement the API in this package.
Example import for consumers using the API in this package:
Import-Package: org.osgi.service.jakartars.client; version="[1.0,2.0)"
Example import for providers implementing the API in this package:
Import-Package: org.osgi.service.jakartars.client; version="[1.0,1.1)"
-
PromiseRxInvoker
- A specialization of the RxInvoker which creates Promise instances. -
SseEventSourceFactory
- A factory for SseEventSource instances.
A specialization of the RxInvoker which creates Promise instances.
Bundles may obtain an instance of a PromiseRxInvoker using a ClientBuilder obtained from the service registry and calling the jakarta.ws.rs.client.Invocation.Builder.rx(Class) method.
Consumers of this API must not implement this type
A factory for SseEventSource instances.
Bundles may obtain an instance of a SseEventSourceFactory using the service registry. This service may then be used to construct SseEventSource instances for the supplied WebTarget.
Consumers of this API must not implement this type
The web target to consume events from
Create a new jakarta.ws.rs.sse.SseEventSource.Builder
a builder which can be used to further configure the event source
Jakarta RESTful Web Services Runtime Package Version 1.0.
Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest. This package has two types of users: the consumers that use the API in this package and the providers that implement the API in this package.
Example import for consumers using the API in this package:
Import-Package: org.osgi.service.jakartars.runtime; version="[1.0,2.0)"
Example import for providers implementing the API in this package:
Import-Package: org.osgi.service.jakartars.runtime; version="[1.0,1.1)"
-
JakartarsServiceRuntime
- The JakartarsServiceRuntime service represents the runtime information of a Jakarta RESTful Web Services Whiteboard implementation. -
JakartarsServiceRuntimeConstants
- Defines standard names for Jakarta RESTful Web Services Runtime Service constants.
The JakartarsServiceRuntime service represents the runtime information of a Jakarta RESTful Web Services Whiteboard implementation.
It provides access to DTOs representing the current state of the service.
The JakartarsServiceRuntime service must be registered with the JakartarsServiceRuntimeConstants.JAKARTA_RS_SERVICE_ENDPOINT service property.
Thread-safe
Consumers of this API must not implement this type
Defines standard names for Jakarta RESTful Web Services Runtime Service constants.
Jakarta RESTful Web Services Runtime Service service property specifying the endpoints upon which the Jakarta RESTful Web Services implementation is available.
An endpoint value is a URL or a relative path, to which the Jakarta
RESTful Web Services Whiteboard implementation is listening. For example,
http://192.168.1.10:8080/
or /myapp/
. A relative path may
be used if the scheme and authority parts of the URL are not known, e.g.
if a bridged Http Whiteboard implementation is used. If the Jakarta
RESTful Web Services Whiteboard implementation is serving the root
context and neither scheme nor authority is known, the value of the
property is "/". Both, a URL and a relative path, must end with a slash.
A Jakarta RESTful Web Services Whiteboard implementation can be listening on multiple endpoints.
The value of this service property must be of type String
,
String[]
, or Collection<String>
.
Jakarta RESTful Web Services Runtime DTO Package Version 1.0.
Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest. This package has two types of users: the consumers that use the API in this package and the providers that implement the API in this package.
Example import for consumers using the API in this package:
Import-Package: org.osgi.service.jakartars.runtime.dto; version="[1.0,2.0)"
Example import for providers implementing the API in this package:
Import-Package: org.osgi.service.jakartars.runtime.dto; version="[1.0,1.1)"
-
ApplicationDTO
- Represents a Jakarta RESTful Web Services Application service. -
BaseApplicationDTO
- Represents common information about a Jakarta RESTful Web Services application service. -
BaseDTO
- Represents common information about a Jakarta RESTful Web Services service. -
BaseExtensionDTO
- Represents common information about a Jakarta RESTful Web Services extension service. -
DTOConstants
- Defines standard constants for the DTOs. -
ExtensionDTO
- Represents a Jakarta RESTful Web Services Extension service currently being hosted by the JakartarsServiceRuntime -
FailedApplicationDTO
- Represents a Jakarta RESTful Web Services service which is currently not being used due to a problem. -
FailedExtensionDTO
- Represents a Jakarta RESTful Web Services Extension service which is currently not being used due to a problem. -
FailedResourceDTO
- Represents a Jakarta RESTful Web Services resource service which is currently not being used due to a problem. -
ResourceDTO
- Represents common information about a Jakarta RESTful Web Services resource service. -
ResourceMethodInfoDTO
- Represents information about a Jakarta RESTful Web Services resource method. -
RuntimeDTO
- Represents the state of a Jakarta RESTful Web Services Service Runtime.
Represents a Jakarta RESTful Web Services Application service.
Not Thread-safe
The RequestPaths handled by statically defined resources in this Application
Represents common information about a Jakarta RESTful Web Services application service.
Not Thread-safe
The base URI of the resource defined by JakartarsWhiteboardConstants.JAKARTA_RS_APPLICATION_BASE.
Returns the representations of the dynamic Jakarta RESTful Web Services extension services associated with this Application. The returned array may be empty if this application is currently not associated with any Jakarta RESTful Web Services extension services.
Returns the representations of the dynamic Jakarta RESTful Web Services resource services associated with this Application. The returned array may be empty if this application is currently not associated with any Jakarta RESTful Web Services Resource services.
Represents common information about a Jakarta RESTful Web Services service.
Not Thread-safe
The name of the service if it set one using JakartarsWhiteboardConstants.JAKARTA_RS_NAME, otherwise this value will contain the generated name for this service
Service property identifying the Jakarta RESTful Web Services service
Represents common information about a Jakarta RESTful Web Services extension service.
Not Thread-safe
Defines standard constants for the DTOs. The error codes are defined to take the same values as used by the Http Service Whiteboard
The service is registered in the service registry with the JakartarsWhiteboardConstants.JAKARTA_RS_NAME property and a service with that name already exists in the runtime
The extension service is registered in the service registry but the service is not registered using a recognized extension type
The service is registered in the service registry with the JakartarsWhiteboardConstants.JAKARTA_RS_APPLICATION_SELECT property and the filters is not matched by any running application.
The service is registered in the service registry with the JakartarsWhiteboardConstants.JAKARTA_RS_EXTENSION_SELECT property and one or more of the filters is not matched.
The service is registered in the service registry but getting the service
fails as it returns null
.
Service is shadowed by another service.
For example, another service with the same service properties but having a higher service ranking. See org.osgi.framework.ServiceReference.compareTo(Object).
Represents a Jakarta RESTful Web Services Extension service currently being hosted by the JakartarsServiceRuntime
Not Thread-safe
The media types consumed by this service, if provided in an Consumes annotation
The resourceDTOs that are mapped to this extension using a NameBinding annotation
The full names of the NameBinding annotations applied to this extension, if any
The media types produced by this service, if provided in an Produces annotation
Represents a Jakarta RESTful Web Services service which is currently not being used due to a problem.
The service represented by this DTO is not used due to a failure, but the BaseApplicationDTO.extensionDTOs and BaseApplicationDTO.resourceDTOs may be non-empty if whiteboard services have been associated with this failed application.
Not Thread-safe
The reason why the resource represented by this DTO is not used.
DTOConstants.FAILURE_REASON_UNKNOWN, DTOConstants.FAILURE_REASON_SERVICE_NOT_GETTABLE, DTOConstants.FAILURE_REASON_VALIDATION_FAILED, DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE, DTOConstants.FAILURE_REASON_REQUIRED_EXTENSIONS_UNAVAILABLE
Represents a Jakarta RESTful Web Services Extension service which is currently not being used due to a problem.
Not Thread-safe
The reason why the extension represented by this DTO is not used.
DTOConstants.FAILURE_REASON_UNKNOWN, DTOConstants.FAILURE_REASON_SERVICE_NOT_GETTABLE, DTOConstants.FAILURE_REASON_VALIDATION_FAILED, DTOConstants.FAILURE_REASON_NOT_AN_EXTENSION_TYPE, DTOConstants.FAILURE_REASON_REQUIRED_EXTENSIONS_UNAVAILABLE
Represents a Jakarta RESTful Web Services resource service which is currently not being used due to a problem.
Not Thread-safe
The reason why the resource represented by this DTO is not used.
DTOConstants.FAILURE_REASON_UNKNOWN, DTOConstants.FAILURE_REASON_SERVICE_NOT_GETTABLE, DTOConstants.FAILURE_REASON_VALIDATION_FAILED, DTOConstants.FAILURE_REASON_REQUIRED_EXTENSIONS_UNAVAILABLE
Represents common information about a Jakarta RESTful Web Services resource service.
Not Thread-safe
The RequestPaths handled by this resource
Represents information about a Jakarta RESTful Web Services resource method. All information is determined by reading the relevant annotations, from the Jakarta RESTful Web Services type and not interpreted further. Dynamic information, or information provided in other ways may not be represented in this DTO.
Not Thread-safe
The mime-type(s) consumed by this resource method, null if Consumes is not defined
The HTTP verb being handled, for example GET, DELETE, PUT, POST, HEAD, OPTIONS, null if no HttpMethod is defined
The NameBinding annotations that apply to this resource method, if any
The path of this resource method. Placeholder information present in the URI pattern will not be interpreted and simply returned as defined.
The mime-type(s) produced by this resource method, null if Produces is not defined
Represents the state of a Jakarta RESTful Web Services Service Runtime.
Not Thread-safe
Returns the representations of the Jakarta RESTful Web Services Application services associated with this Runtime. The returned array may be empty if this whiteboard is currently not associated with any Jakarta RESTful Web Services application services.
Returns the current state of the default application for this Runtime.
Returns the representations of the Jakarta RESTful Web Services extension services targeted to this runtime but currently not used due to some problem. The returned array may be empty.
Returns the representations of the Jakarta RESTful Web Services extension services targeted to this runtime but currently not used due to some problem. The returned array may be empty.
Returns the representations of the Jakarta RESTful Web Services resource services targeted to this runtime but currently not used due to some problem. The returned array may be empty.
The DTO for the corresponding JakartarsServiceRuntime
. This value
is never null
.
Jakarta RESTful Web Services Whiteboard Package Version 1.0.
Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest. This package has two types of users: the consumers that use the API in this package and the providers that implement the API in this package.
Example import for consumers using the API in this package:
Import-Package: org.osgi.service.jakartars.whiteboard; version="[1.0,2.0)"
Example import for providers implementing the API in this package:
Import-Package: org.osgi.service.jakartars.whiteboard; version="[1.0,1.1)"
-
JakartarsWhiteboardConstants
- Defines standard constants for the Jakarta RESTful Web Services Whiteboard services.
Defines standard constants for the Jakarta RESTful Web Services Whiteboard services.
Service property specifying the base URI mapping for a Jakarta RESTful Web Services application service.
The specified uri is used to determine whether a request should be mapped to the resource. Services without this service property are ignored.
The value of this service property must be of type String
, and
will have a "/" prepended if no "/" exists.
If two applications are registered with the same base uri then the lower ranked service is failed with a cause of DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE
Service property specifying the target application for a Jakarta RESTful Web Services resource or extension service.
The specified filter(s) is/are used to determine whether a resource should be included in a particular application. Services without this service property are bound to the default Application.
If a filter property is registered and no application running in the whiteboard matches the filter then the service will be failed with a cause of DTOConstants.FAILURE_REASON_REQUIRED_APPLICATION_UNAVAILABLE
The value of this service property must be of type String+
, and
each entry must be a valid OSGi filter.
The property key which can be used to find the application service properties inside an injected Configuration
The name of the default Jakarta RESTful Web Services application in every Whiteboard instance.
Service property specifying that a Jakarta RESTful Web Services resource service should be processed by the whiteboard.
The value of this service property must be of type String
or
Boolean and set to "true" or true
.
A service providing this property must be registered as one or more of the following types:
-
MessageBodyReader
-
MessageBodyWriter
-
ContainerRequestFilter
-
ContainerResponseFilter
-
ReaderInterceptor
-
WriterInterceptor
-
ContextResolver
-
ExceptionMapper
-
ParamConverterProvider
-
Feature
-
DynamicFeature
If a service with this property does not match any of the defined types then it is registered as a failure DTO with the error code DTOConstants.FAILURE_REASON_NOT_AN_EXTENSION_TYPE,
A Service property specifying one or more target filters used to select the set of Jakarta RESTful Web Services extension services required to support this whiteboard service.
A Jakarta RESTful Web Services Whiteboard service may require one or more
extensions to be available so that it can function. For example a
resource which declares that it @Produces("text/json")
requires a MessageBodyWriter which supports JSON to be available.
This service property provides a String+ set of LDAP filters which will be applied to the service properties of all extensions available in the Jakarta RESTful Web Services container. If all of the filters are satisfied then this service is eligible to be hosted by the Jakarta RESTful Web Services container.
This service property may be declared by any Jakarta RESTful Web Services whiteboard service, whether it is a resource, or an extension.
If this service property is not specified, then no extensions are required.
If one or more filter properties are registered and no suitable extension(s) are available then the service will be failed with a cause of DTOConstants.FAILURE_REASON_REQUIRED_EXTENSIONS_UNAVAILABLE
The value of this service property must be of type String
and be
a valid filter string.
A service property specifying that a Jakarta RESTful Web Services extension service, application service, or whiteboard implementation provides support for reading from and writing to a specific media type.
The value of this property will be one or more media type identifiers,
and where possible IANA registered names, such as
application/json
should be used. The value must not be a
wildcard type. Support for multiple media types that use the same suffix
should be supported by registering the media type associated with the
suffix.
Service property specifying the name of a Jakarta RESTful Web Services whiteboard service.
This name is provided as a property on the registered Endpoint service so that the URI for a particular Jakarta RESTful Web Services service can be identified. If this service property is not specified, then no Endpoint information will be registered for this resource.
Resource names must be unique among all services associated with a single Whiteboard implementation. If a clashing name is registered then the lower ranked service will be failed with a cause of DTOConstants.FAILURE_REASON_DUPLICATE_NAME
The value of this service property must be of type String
.
Service property specifying that a Jakarta RESTful Web Services resource should be processed by the whiteboard.
The value of this service property must be of type String
or
Boolean and set to "true" or true
.
The name of the implementation capability for the Whiteboard Specification for Jakarta RESTful Web Services.
The version of the implementation capability for the Whiteboard Specification for Jakarta RESTful Web Services.
Service property specifying the target filter to select the Jakarta RESTful Web Services Whiteboard implementation to process the service.
A Jakarta RESTful Web Services Whiteboard implementation can define any number of service properties which can be referenced by the target filter. The service properties should always include the osgi.jakartars.endpoint service property if the endpoint information is known.
If this service property is not specified, then all Jakarta RESTful Web Services Whiteboard implementations can process the service.
The value of this service property must be of type String
and be
a valid filter string.
Jakarta RESTful Web Services Whiteboard Annotations Package Version 1.0.
This package contains annotations that can be used to require the Jakarta RESTful Web Services Whiteboard implementation.
Bundles should not normally need to import this package as the annotations are only used at build-time.
-
RequireJakartarsWhiteboard
- This annotation can be used to require the Jakarta RESTful Web Services Whiteboard implementation.
This annotation can be used to require the Jakarta RESTful Web Services Whiteboard implementation. It can be used directly, or as a meta-annotation.
This annotation is applied to several of the Jakarta RESTful Web Services Whiteboard component property annotations meaning that it does not normally need to be applied to Declarative Services components which use the Jakarta RESTful Web Services Whiteboard.
CLASS
TYPE
, PACKAGE
Jakarta RESTful Web Services Whiteboard Package Version 1.0.
Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest. This package has two types of users: the consumers that use the API in this package and the providers that implement the API in this package.
Example import for consumers using the API in this package:
Import-Package: org.osgi.service.jakartars.whiteboard; version="[1.0,2.0)"
Example import for providers implementing the API in this package:
Import-Package: org.osgi.service.jakartars.whiteboard; version="[1.0,1.1)"
-
JakartarsApplicationBase
- Component Property Type for theosgi.jakartars.application.base
service property. -
JakartarsApplicationSelect
- Component Property Type for theosgi.jakartars.application.select
service property. -
JakartarsExtension
- Component Property Type for theosgi.jakartars.extension
service property. -
JakartarsExtensionSelect
- Component Property Type for theosgi.jakartars.extension.select
service property. -
JakartarsMediaType
- Component Property Type for theosgi.jakartars.media.type
service property. -
JakartarsName
- Component Property Type for theosgi.jakartars.name
service property. -
JakartarsResource
- Component Property Type for theosgi.jakartars.resource
service property. -
JakartarsWhiteboardTarget
- Component Property Type for theosgi.jakartars.whiteboard.target
service property. -
JSONRequired
- Component Property Type for requiring JSON media type support using the JakartarsWhiteboardConstants.JAKARTA_RS_MEDIA_TYPE service property.
Component Property Type for the osgi.jakartars.application.base
service property.
This annotation can be used on a Jakarta RESTful Web Services whiteboard application service to declare the value of the JakartarsWhiteboardConstants.JAKARTA_RS_APPLICATION_BASE service property.
Component Property Types
CLASS
TYPE
Service property providing a base context URI for a Jakarta RESTful Web Services whiteboard application.
The base URI for this application.
Component Property Type for the osgi.jakartars.application.select
service property.
This annotation can be used on a Jakarta RESTful Web Services whiteboard resource or extension service to declare the value of the JakartarsWhiteboardConstants.JAKARTA_RS_APPLICATION_SELECT service property.
Component Property Types
CLASS
TYPE
Service property providing a OSGi filter(s) identifying the application(s) to which this service should be bound.
The filter(s) for selecting the application(s) to bind to.
Component Property Type for the osgi.jakartars.extension
service
property.
This annotation can be used on a Jakarta RESTful Web Services extension service to declare the value of the JakartarsWhiteboardConstants.JAKARTA_RS_EXTENSION service property.
Component Property Types
CLASS
TYPE
Component Property Type for the osgi.jakartars.extension.select
service property.
This annotation can be used on a Jakarta RESTful Web Services whiteboard resource or extension to declare the value of the JakartarsWhiteboardConstants.JAKARTA_RS_EXTENSION_SELECT service property.
Component Property Types
CLASS
TYPE
Service property providing one or more OSGi filters identifying the extension(s) or application features which this service requires to work.
The filters for selecting the extensions to require.
Component Property Type for the osgi.jakartars.media.type
service
property.
This annotation can be used on a Jakarta RESTful Web Services whiteboard extension or application to declare the value of the JakartarsWhiteboardConstants.JAKARTA_RS_MEDIA_TYPE service property.
Component Property Types
CLASS
TYPE
Service property identifying the name(s) of media types supported by this service.
The Jakarta RESTful Web Services media types supported.
Component Property Type for the osgi.jakartars.name
service property.
This annotation can be used on a Jakarta RESTful Web Services whiteboard service to declare the value of the JakartarsWhiteboardConstants.JAKARTA_RS_NAME service property.
Component Property Types
CLASS
TYPE
Service property identifying the name of a Jakarta RESTful Web Services service for processing by the whiteboard.
The Jakarta RESTful Web Services whiteboard service name.
Component Property Type for the osgi.jakartars.resource
service
property.
This annotation can be used on a Jakarta RESTful Web Services whiteboard resource to declare the value of the JakartarsWhiteboardConstants.JAKARTA_RS_RESOURCE service property.
Component Property Types
CLASS
TYPE
Component Property Type for the osgi.jakartars.whiteboard.target
service property.
This annotation can be used on a Jakarta RESTful Web Services whiteboard resource or extension service to declare the value of the JakartarsWhiteboardConstants.JAKARTA_RS_WHITEBOARD_TARGET service property.
Component Property Types
CLASS
TYPE
Service property providing an OSGi filter identifying the whiteboard(s) to which this service should be bound.
The filter for selecting the whiteboards to bind to.
Component Property Type for requiring JSON media type support using the JakartarsWhiteboardConstants.JAKARTA_RS_MEDIA_TYPE service property.
This annotation can be used on a Jakarta RESTful Web Services whiteboard resource to declare require that JSON support is available before the resource becomes active. It also adds an optional Requirement for a service providing this media type to aid with provisioning.
Component Property Types
CLASS
TYPE
Provides an extension selection filter for an extension supporting the JSON media type
A filter requiring an osgi.jakartars.media.type
of
application/json
[1]Jakarta RESTful Web Services 3.0 Specificationhttps://jakarta.ee/specifications/restful-ws/3.0/
[2]Portable Java Contract Definitionshttps://docs.osgi.org/reference/portable-java-contracts.html
[3]Whiteboard Patternhttps://docs.osgi.org/whitepaper/whiteboard-pattern/
[4]IANA Media Type Registrationshttps://www.iana.org/assignments/media-types/media-types.xhtml
[5]IANA Media Type Suffix Registrationshttps://www.iana.org/assignments/media-type-structured-suffix/media-type-structured-suffix.xhtml
[6]JAX-RS Service Whiteboard Specificationhttps://docs.osgi.org/specification/osgi.cmpn/8.0.0/service.jaxrs.html
-
This specification is providing the same functionality as its predecessor, [6] JAX-RS Service Whiteboard Specification, with the switch from the JAX-RS API to the Jakarta RESTful Web Services API.
Due to the naming change numerous constants have been renamed, including the service properties used in the specification. This allows the old and new specifications to coexist in the same framework.
-
The Application Selection Filter property has changed from a single String to a String+, allowing multiple filters to be supplied.