4.10JAX-RS Server

 

The HAPI FHIR Plain Server (RestfulServer) is implemented as a standard JEE Servlet, meaning that it can be deployed in any compliant JEE web container.

For users who already have an existing JAX-RS infrastructure, and who would like to use that technology foor their FHIR stack as well, a module exists which implements the server using JAX-RS technology.

The JAX-RS module is a community-supported module that was not developed by the core HAPI FHIR team. Before decid the HAPI FHIR JAX-RS module, please be aware that it does not have as complete of support for the full FHIR REST specification as the Plain Server. If you need a feature that is missing, please consiider adding it and making a pull request!

Features

The server currently supports:

The primary intention for this project is to ensure that other web technologies (JAX-RS in this case) can be used together with the base-server functionality. An example server can be found in the Git repo here.

4.10.1JAX-RS Implementation specifics

 

The set-up of a JAX-RS server goes beyond the scope of this documentation. The implementation of the server follows the same pattern as the standard server. It is required to put the correct annotation on the methods in the Resource Providers in order to be able to call them.

Implementing a JAX-RS Resource Provider requires some JAX-RS annotations. The @Path annotation needs to define the resource path. The @Produces annotation needs to declare the produced formats. The constructor needs to pass the class of the object explicitely in order to avoid problems with proxy classes in a Java EE environment.

It is necessary to extend the abstract class AbstractJaxRsResourceProvide.

@Path("/Patient")
@Produces({ MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML })
public class JaxRsPatientRestProvider extends AbstractJaxRsResourceProvider<Patient> {

  public JaxRsPatientRestProvider() {
    super(JaxRsPatientRestProvider.class);
  }

Extended Operations

Extended Operations require the correct JAX-RS ( @Path, @GET or @POST annotations. The body of the method needs to call the method [AbstractJaxRsResourceProvider#customOperation](/hapi-fhir/apidocs/hapi-fhir-jaxrsserver-base/ca/uhn/fhir/jaxrs/server/AbstractJaxRsResourceProvider.html#customOperation(java.lang.String,ca.uhn.fhir.rest.api.RequestTypeEnum,java.lang.String,java.lang.String,ca.uhn.fhir.rest.api.RestOperationTypeEnum) with the correct parameters. The server will then call the method with corresponding name.

@GET
@Path("/{id}/$someCustomOperation")
public Response someCustomOperationUsingGet(@PathParam("id") String id, String resource) throws Exception {
  return customOperation(resource, RequestTypeEnum.GET, id, "$someCustomOperation",
          RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE);
}

@Operation(name = "someCustomOperation", idempotent = true, returnParameters = {
    @OperationParam(name = "return", type = StringDt.class) })
public Parameters someCustomOperation(@IdParam IdType myId, @OperationParam(name = "dummy") StringDt dummyInput) {
  Parameters parameters = new Parameters();
  parameters.addParameter().setName("return").setValue(new StringType("My Dummy Result"));
  return parameters;
}

In order to create the conformance profile, a conformance provider class needs to be deployed which exports the provider's conformance statements. These providers need to be returned as the result of the method AbstractJaxRsConformanceProvider#getProviders. This method is called once, during PostConstruct.

@Path("")
@Stateless
@Produces({ MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML })
public class JaxRsConformanceProvider extends AbstractJaxRsConformanceProvider {

  @EJB
  private JaxRsPatientRestProvider provider;

  public JaxRsConformanceProvider() {
    super("My Server Description", "My Server Name", "My Server Version");
  }

  @Override
  protected ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> getProviders() {
    ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> map = new ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider>();
    map.put(JaxRsConformanceProvider.class, this);
    map.put(JaxRsPatientRestProvider.class, provider);
    return map;
  }
}

4.10.2A Complete Example

 

A complete example showing how to implement a JAX-RS RESTful server can be found in our Git repo here: