The standard server is implemented using Servlet technology. A module exists which implements the server using JAX-RS technology. This enables the usage of existing Java EE interceptors and annotations. This module does not provide the full set of features. The server currently supports Conformance Statements, @Read, @Search, @Create, @Update, @Delete and @Operation.

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.

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

@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 require the correct JAX-RS ( @Path, @GET or @POST) annotations. The body of the method needs to call the method AbstractJaxRsResourceProvider#customOperation 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 IdDt myId, @OperationParam(name = "dummy") StringDt dummyInput) {
  Parameters parameters = new Parameters();
  parameters.addParameter().setName("return").setValue(new StringDt("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 AbstractJaxRsResourceProvider#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 Version", "My Server Description", "My Server Name");
  }

  @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;
  }
}

A Complete Example

A complete example showing how to implement a JAX-RS RESTful server can be found in our Git repo here: https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jaxrsserver-example

Back to top

Reflow Maven skin by Andrius Velykis.