Fix to valueset expansion logic (#1613)

* Fox to valueset expansion logic

* Work on docs

* Docs tweaks

* Docs tweaks

* Fix test

* Remove unused class

* Add changelog
This commit is contained in:
James Agnew 2019-12-01 21:21:19 -05:00 committed by GitHub
parent 00c7b047ac
commit 86bd9a28fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
79 changed files with 3554 additions and 1551 deletions

View File

@ -41,20 +41,30 @@ import java.util.*;
*/
public final class DateUtils {
/**
* GMT TimeZone
*/
public static final TimeZone GMT = TimeZone.getTimeZone("GMT");
/**
* Date format pattern used to parse HTTP date headers in RFC 1123 format.
*/
private static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
@SuppressWarnings("WeakerAccess")
public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
/**
* Date format pattern used to parse HTTP date headers in RFC 1036 format.
*/
private static final String PATTERN_RFC1036 = "EEE, dd-MMM-yy HH:mm:ss zzz";
@SuppressWarnings("WeakerAccess")
public static final String PATTERN_RFC1036 = "EEE, dd-MMM-yy HH:mm:ss zzz";
/**
* Date format pattern used to parse HTTP date headers in ANSI C
* {@code asctime()} format.
*/
private static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
@SuppressWarnings("WeakerAccess")
public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
private static final String[] DEFAULT_PATTERNS = new String[]{
PATTERN_RFC1123,
PATTERN_RFC1036,

View File

@ -109,14 +109,16 @@ public class FhirValidator {
*
* @param theValidator
* The validator module. Must not be null.
* @return Returns a reference to <code>this</code> for easy method chaining.
*/
public synchronized void registerValidatorModule(IValidatorModule theValidator) {
public synchronized FhirValidator registerValidatorModule(IValidatorModule theValidator) {
Validate.notNull(theValidator, "theValidator must not be null");
ArrayList<IValidatorModule> newValidators = new ArrayList<IValidatorModule>(myValidators.size() + 1);
newValidators.addAll(myValidators);
newValidators.add(theValidator);
myValidators = newValidators;
return this;
}
/**

View File

@ -93,6 +93,12 @@
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-testpage-overlay</artifactId>
<version>4.2.0-SNAPSHOT</version>
<classifier>classes</classifier>
</dependency>
</dependencies>
<build>

View File

@ -22,65 +22,51 @@ package ca.uhn.hapi.fhir.docs;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.util.BundleUtil;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.RelatedPerson;
import org.hl7.fhir.r4.model.Patient;
import java.util.HashSet;
import java.util.Set;
import java.util.ArrayList;
import java.util.List;
/**
* @author Bill de Beaubien on 1/13/2016.
*/
public class BundleFetcher {
public static void fetchRestOfBundle(IGenericClient theClient, Bundle theBundle) {
// we need to keep track of which resources are already in the bundle so that if other resources (e.g. Practitioner) are _included,
// we don't end up with multiple copies
Set<String> resourcesAlreadyAdded = new HashSet<String>();
addInitialUrlsToSet(theBundle, resourcesAlreadyAdded);
Bundle partialBundle = theBundle;
for (;;) {
if (partialBundle.getLink(IBaseBundle.LINK_NEXT) != null) {
partialBundle = theClient.loadPage().next(partialBundle).execute();
addAnyResourcesNotAlreadyPresentToBundle(theBundle, partialBundle, resourcesAlreadyAdded);
} else {
break;
}
}
// the self and next links for the aggregated bundle aren't really valid anymore, so remove them
theBundle.getLink().clear();
}
private static void addInitialUrlsToSet(Bundle theBundle, Set<String> theResourcesAlreadyAdded) {
for (Bundle.BundleEntryComponent entry : theBundle.getEntry()) {
theResourcesAlreadyAdded.add(entry.getFullUrl());
}
}
public static void main(String[] args) {
// START SNIPPET: loadAll
// Create a context and a client
FhirContext ctx = FhirContext.forR4();
String serverBase = "http://hapi.fhr.org/baseR4";
IGenericClient client = ctx.newRestfulGenericClient(serverBase);
private static void addAnyResourcesNotAlreadyPresentToBundle(Bundle theAggregatedBundle, Bundle thePartialBundle, Set<String> theResourcesAlreadyAdded) {
for (Bundle.BundleEntryComponent entry : thePartialBundle.getEntry()) {
if (!theResourcesAlreadyAdded.contains(entry.getFullUrl())) {
theResourcesAlreadyAdded.add(entry.getFullUrl());
theAggregatedBundle.getEntry().add(entry);
}
}
}
// We'll populate this list
List<IBaseResource> patients = new ArrayList<>();
public static void main(String[] args) {
FhirContext ctx = FhirContext.forR4();
String serverBase = "http://fhirtest.uhn.ca/baseR4";
IGenericClient client = ctx.newRestfulGenericClient(serverBase);
// use RelatedPerson because there aren't that many on the server
Bundle bundle = client.search().forResource(RelatedPerson.class).returnBundle(Bundle.class).execute();
BundleFetcher.fetchRestOfBundle(client, bundle);
if (bundle.getTotal() != bundle.getEntry().size()) {
System.out.println("Counts didn't match! Expected " + bundle.getTotal() + " but bundle only had " + bundle.getEntry().size() + " entries!");
}
// We'll do a search for all Patients and extract the first page
Bundle bundle = client
.search()
.forResource(Patient.class)
.where(Patient.NAME.matches().value("smith"))
.returnBundle(Bundle.class)
.execute();
patients.addAll(BundleUtil.toListOfResources(ctx, bundle));
// IParser parser = ctx.newXmlParser().setPrettyPrint(true);
// System.out.println(parser.encodeResourceToString(bundle));
// Load the subsequent pages
while (bundle.getLink(IBaseBundle.LINK_NEXT) != null) {
bundle = client
.loadPage()
.next(bundle)
.execute();
patients.addAll(BundleUtil.toListOfResources(ctx, bundle));
}
}
System.out.println("Loaded " + patients.size() + " patients!");
// END SNIPPET: loadAll
}
}

View File

@ -95,14 +95,14 @@ public class ClientTransactionExamples {
// Log the request
FhirContext ctx = FhirContext.forR4();
System.out.println(ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(bundle));
System.out.println(ctx.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle));
// Create a client and post the transaction to the server
IGenericClient client = ctx.newRestfulGenericClient("http://fhirtest.uhn.ca/baseR4");
IGenericClient client = ctx.newRestfulGenericClient("http://hapi.fhir.org/baseR4");
Bundle resp = client.transaction().withBundle(bundle).execute();
// Log the response
System.out.println(ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
System.out.println(ctx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resp));
//END SNIPPET: conditional
}

View File

@ -0,0 +1,62 @@
package ca.uhn.hapi.fhir.docs;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.to.FhirTesterMvcConfig;
import ca.uhn.fhir.to.TesterConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
// START SNIPPET: file
/**
* This spring config file configures the web testing module. It serves two
* purposes:
* 1. It imports FhirTesterMvcConfig, which is the spring config for the
* tester itself
* 2. It tells the tester which server(s) to talk to, via the testerConfig()
* method below
*/
@Configuration
@Import(FhirTesterMvcConfig.class)
public class FhirTesterConfig {
/**
* This bean tells the testing webpage which servers it should configure itself
* to communicate with. In this example we configure it to talk to the local
* server, as well as one public server. If you are creating a project to
* deploy somewhere else, you might choose to only put your own server's
* address here.
*
* Note the use of the ${serverBase} variable below. This will be replaced with
* the base URL as reported by the server itself. Often for a simple Tomcat
* (or other container) installation, this will end up being something
* like "http://localhost:8080/hapi-fhir-jpaserver-example". If you are
* deploying your server to a place with a fully qualified domain name,
* you might want to use that instead of using the variable.
*/
@Bean
public TesterConfig testerConfig() {
TesterConfig retVal = new TesterConfig();
retVal
.addServer()
.withId("home")
.withFhirVersion(FhirVersionEnum.DSTU2)
.withBaseUrl("${serverBase}/fhir")
.withName("Local Tester")
.addServer()
.withId("hapi")
.withFhirVersion(FhirVersionEnum.DSTU2)
.withBaseUrl("http://fhirtest.uhn.ca/baseDstu2")
.withName("Public HAPI Test Server");
/*
* Use the method below to supply a client "factory" which can be used
* if your server requires authentication
*/
// retVal.setClientFactory(clientFactory);
return retVal;
}
}
// END SNIPPET: file

View File

@ -427,9 +427,8 @@ public class GenericClientExample {
public static void history() {
IGenericClient client = FhirContext.forDstu2().newRestfulGenericClient("");
{
Bundle response;
// START SNIPPET: historyDstu2
response = client
Bundle response = client
.history()
.onServer()
.returnBundle(Bundle.class)
@ -437,9 +436,8 @@ public class GenericClientExample {
// END SNIPPET: historyDstu2
}
{
Bundle response;
// START SNIPPET: historyFeatures
response = client
Bundle response = client
.history()
.onServer()
.returnBundle(Bundle.class)

View File

@ -33,6 +33,7 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.hapi.ctx.DefaultProfileValidationSupport;
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport;
import org.hl7.fhir.r4.hapi.validation.FhirInstanceValidator;
import org.hl7.fhir.r4.hapi.validation.PrePopulatedValidationSupport;
import org.hl7.fhir.r4.hapi.validation.ValidationSupportChain;
import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.terminologies.ValueSetExpander;
@ -42,22 +43,20 @@ import java.io.File;
import java.io.FileReader;
import java.util.List;
@SuppressWarnings("serial")
@SuppressWarnings({"serial", "unused"})
public class ValidatorExamples {
public void validationIntro() {
// START SNIPPET: validationIntro
FhirContext ctx = FhirContext.forDstu3();
FhirContext ctx = FhirContext.forR4();
// Ask the context for a validator
FhirValidator validator = ctx.newValidator();
// Create some modules and register them
IValidatorModule module1 = new SchemaBaseValidator(ctx);
validator.registerValidatorModule(module1);
IValidatorModule module2 = new SchematronBaseValidator(ctx);
validator.registerValidatorModule(module2);
// Create a validator modules and register it
IValidatorModule module = new FhirInstanceValidator();
validator.registerValidatorModule(module);
// Pass a resource in to be validated. The resource can
// be an IBaseResource instance, or can be a raw String
// containing a serialized resource as text.
@ -82,7 +81,7 @@ public class ValidatorExamples {
// Create a context, set the error handler and instruct
// the server to use it
FhirContext ctx = FhirContext.forDstu3();
FhirContext ctx = FhirContext.forR4();
ctx.setParserErrorHandler(new StrictErrorHandler());
setFhirContext(ctx);
}
@ -93,19 +92,19 @@ public class ValidatorExamples {
@SuppressWarnings("unused")
public void enableValidation() {
// START SNIPPET: clientValidation
FhirContext ctx = FhirContext.forDstu3();
FhirContext ctx = FhirContext.forR4();
ctx.setParserErrorHandler(new StrictErrorHandler());
// This client will have strict parser validation enabled
IGenericClient client = ctx.newRestfulGenericClient("http://fhirtest.uhn.ca/baseDstu3");
IGenericClient client = ctx.newRestfulGenericClient("http://hapi.fhir.org/baseR4");
// END SNIPPET: clientValidation
}
public void parserValidation() {
// START SNIPPET: parserValidation
FhirContext ctx = FhirContext.forDstu3();
FhirContext ctx = FhirContext.forR4();
// Create a parser and configure it to use the strict error handler
IParser parser = ctx.newXmlParser();
@ -122,7 +121,7 @@ public class ValidatorExamples {
public void validateResource() {
// START SNIPPET: basicValidation
// As always, you need a context
FhirContext ctx = FhirContext.forDstu3();
FhirContext ctx = FhirContext.forR4();
// Create and populate a new patient object
Patient p = new Patient();
@ -176,7 +175,7 @@ public class ValidatorExamples {
private static void instanceValidator() throws Exception {
// START SNIPPET: instanceValidator
FhirContext ctx = FhirContext.forDstu3();
FhirContext ctx = FhirContext.forR4();
// Create a FhirInstanceValidator and register it to a validator
FhirValidator validator = ctx.newValidator();
@ -226,7 +225,7 @@ public class ValidatorExamples {
private static void instanceValidatorCustom() throws Exception {
// START SNIPPET: instanceValidatorCustom
FhirContext ctx = FhirContext.forDstu3();
FhirContext ctx = FhirContext.forR4();
// Create a FhirInstanceValidator and register it to a validator
FhirValidator validator = ctx.newValidator();
@ -315,6 +314,43 @@ public class ValidatorExamples {
// END SNIPPET: instanceValidatorCustom
}
public void validateSupplyProfiles() {
StructureDefinition someStructureDefnition = null;
ValueSet someValueSet = null;
String input = null;
// START SNIPPET: validateSupplyProfiles
FhirContext ctx = FhirContext.forR4();
// Create a PrePopulatedValidationSupport and load it with our custom structures
PrePopulatedValidationSupport prePopulatedSupport = new PrePopulatedValidationSupport();
// In this example we're loading two things, but in a real scenario we might
// load many StructureDefinitions, ValueSets, CodeSystems, etc.
prePopulatedSupport.addStructureDefinition(someStructureDefnition);
prePopulatedSupport.addValueSet(someValueSet);
// We'll still use DefaultProfileValidationSupport since derived profiles generally
// rely on built-in profiles also being available
DefaultProfileValidationSupport defaultSupport = new DefaultProfileValidationSupport();
// We'll create a chain that includes both the pre-populated and default. We put
// the pre-populated (custom) support module first so that it takes precedence
ValidationSupportChain supportChain = new ValidationSupportChain();
supportChain.addValidationSupport(prePopulatedSupport);
supportChain.addValidationSupport(defaultSupport);
// Create a validator using the FhirInstanceValidator module. We can use this
// validator to perform validation
FhirInstanceValidator validatorModule = new FhirInstanceValidator(supportChain);
FhirValidator validator = ctx.newValidator().registerValidatorModule(validatorModule);
ValidationResult result = validator.validateWithResult(input);
// END SNIPPET: validateSupplyProfiles
}
@SuppressWarnings("unused")
private static void validateFiles() throws Exception {

View File

@ -34,7 +34,7 @@ To see a sample Gradle file for a working Android project using HAPI FHIR, see t
# Performance
On mobile devices, performance problems are particularly noticeable. This is made worse by the fact that some economy Android devices have much slower performance than modern desktop computers. See the [Client Configuration Performance](/docs/client/rest_client_http_config.html#performance) page for some tips on how to improve client performance.
On mobile devices, performance problems are particularly noticeable. This is made worse by the fact that some economy Android devices have much slower performance than modern desktop computers. See the [Client Configuration Performance](/docs/client/client_configuration.html#performance) page for some tips on how to improve client performance.
# Examples

View File

@ -30,7 +30,13 @@ There are a few options available to work around this fact:
# Contributing
### My build is failing with the following error: *[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.19.1:test (default-test) on project hapi-fhir-jpaserver-base: Execution default-test of goal org.apache.maven.plugins:maven-surefire-plugin:2.19.1:test failed: The forked VM terminated without properly saying goodbye. VM crash or System.exit called?*
### My build is failing with the following error: *The forked VM terminated without properly saying goodbye. VM crash or System.exit called?*
The complete error message typically resembles:
```
Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.19.1:test (default-test) on project hapi-fhir-jpaserver-base: Execution default-test of goal org.apache.maven.plugins:maven-surefire-plugin:2.19.1:test failed: The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
```
This typically means that your build is running out of memory. HAPI's unit tests execute by default in multiple threads (the thread count is determined by the number of CPU cores available) so in an environment with lots of cores but not enough RAM, you may run out. If you are getting this error, try executing the build with the following arguments:
@ -38,4 +44,4 @@ This typically means that your build is running out of memory. HAPI's unit tests
mvn -P ALLMODULES,NOPARALLEL install
```
See [Hacking HAPI FHIR](/hacking.html) for more information on the build process.
See [Hacking HAPI FHIR](/docs/contributing/hacking_guide.html) for more information on the build process.

View File

@ -58,9 +58,9 @@ Note that some popular libraries (e.g. Spring Framework) also use commons-loggin
# Client Payload Logging
To enable detailed logging of client requests and responses (what URL is being requested, what headers and payload are being received, etc.), an interceptor may be added to the client which logs each transaction. See [Logging Requests and Responses](./doc_rest_client_interceptor.html#req_resp_logging) for more information.
To enable detailed logging of client requests and responses (what URL is being requested, what headers and payload are being received, etc.), an interceptor may be added to the client which logs each transaction. See [Logging Requests and Responses](/docs/interceptors/built_in_client_interceptors.html#req_resp_logging) for more information.
# Server Request Logging
To enable detailed logging of server requests and responses, an interceptor may be added to the server which logs each transaction. See [Logging Server Requests](./doc_rest_server_interceptor.html#Logging) for more information.
To enable detailed logging of server requests and responses, an interceptor may be added to the server which logs each transaction. See [Logging Server Requests](/docs/interceptors/built_in_server_interceptors.html#logging_server_requests) for more information.

View File

@ -0,0 +1,56 @@
# Annotation Client
HAPI also provides a second style of client, called the *annotation-driven* client. If you are using the
[Generic (Fluent) Client](./generic_client.html) do not necessarily need to read this page.
The design of the annotation-driven client is intended to be similar to that of JAX-WS, so users of that specification should be comfortable with this one. It uses a user-defined interface containing special annotated methods which HAPI binds to calls against a server.
The annotation-driven client is particularly useful if you have a server that exposes a set of specific operations (search parameter combinations, named queries, etc.) and you want to let developers have a stongly/statically typed interface to that server.
There is no difference in terms of capability between the two styles of client. There is simply a difference in programming style and complexity. It is probably safe to say that the generic client is easier to use and leads to more readable code, at the expense of not giving any visibility into the specific capabilities of the server you are interacting with.
## Defining A Restful Client Interface
The first step in creating an annotation-driven client is to define a restful client interface.
A restful client interface class must extend the [IRestfulClient](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/client/api/IRestfulClient.html) interface, and will contain one or more methods which have been annotated with special annotations indicating which REST operation
that method supports.
Below is a simple example of a resource provider which supports the [read](http://hl7.org/implement/standards/fhir/http.html#read) operation (i.e. retrieve a single resource by ID) as well as the [search](http://hl7.org/implement/standards/fhir/http.html#search) operation (i.e. find any resources matching a given criteria) for a specific search criteria.
You may notice that this interface looks a lot like the Resource Provider which is defined for use by the RESTful server. In fact, it supports all of the same annotations and is essentially identical, other than the fact that for a client you must use an interface but for a server you must use a concrete class with method implementations.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/IRestfulClient.java|provider}}
```
You will probably want to add more methods to your client interface.
See the [REST Operations](/docs/server_plain/rest_operations.html) page in the server documentation section to see examples of how these methods should look.
## Instantiating the Client
Once your client interface is created, all that is left is to create a FhirContext and instantiate the client and you are ready to start using it.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ExampleRestfulClient.java|client}}
```
# Configuring Encoding (JSON/XML)
Restful client interfaces that you create will also extend the interface [IRestfulClient](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/client/api/IRestfulClient.html), which comes with some helpful methods for configuring the way that the client will interact with the server.
The following snippet shows how to configure the cliet to explicitly request JSON or XML responses, and how to request "pretty printed" responses on servers that support this (HAPI based servers currently).
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ClientExamples.java|clientConfig}}
```
## A Complete Example
The following is a complete example showing a RESTful client using HAPI FHIR.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/CompleteExampleClient.java|client}}
```

View File

@ -0,0 +1,83 @@
# Client Configuration
This page outlines ways that the client can be configured for specific behaviour.
<a name="performance"/>
# Performance
## Server Conformance Check
By default, the client will query the server before the very first operation to download the server's conformance/metadata statement and verify that the server is appropriate for the given client. This check is only done once per server endpoint for a given FhirContext.
This check is useful to prevent bugs or unexpected behaviour when talking to servers. It may introduce unneccesary overhead however in circumstances where the client and server are known to be compatible. The following example shows how to disable this check.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|dontValidate}}
```
## Deferred Model Scanning
By default, HAPI will scan each model type it encounters as soon as it encounters it. This scan includes a check for all fields within the type, and makes use of reflection to do this.
While this process is not particularly significant on reasonably performant machines (one benchmark showed that this takes roughly 0.6 seconds to scan all types on one developer workstation), on some devices (e.g. Android phones where every millisecond counts) it may be desirable to defer this scan.
When the scan is deferred, objects will only be scanned when they are actually accessed, meaning that only types that are actually used in an application get scanned.
The following example shows how to defer model scanning:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|deferModelScanning}}
```
# Configuring the HTTP Client
REST clients (both Generic and Annotation-Driven) use [Apache HTTP Client](http://hc.apache.org/httpcomponents-client-ga/) as a provider by default (except on Android, where [OkHttp](http://square.github.io/okhttp/) is the default).
The Apache HTTP Client is very powerful and extremely flexible, but can be confusing at first to configure, because of the low-level approach that the library uses.
In many cases, the default configuration should suffice. HAPI FHIR also encapsulates some of the more common configuration settings you might want to use (socket timesouts, proxy settings, etc.) so that these can be configured through HAPI's API without needing to understand the underlying HTTP Client library.
This configuration is provided by accessing the [IRestfulClientFactory](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/client/api/IRestfulClientFactory.html) class from the FhirContext.
Note that individual requests and responses can be tweaked using [Client Interceptors](/docs/interceptors/client_interceptors.html). This approach is generally useful for configuration involving tweaking the HTTP request/response, such as adding authorization headers or logging.
## Setting Socket Timeouts
The following example shows how to configure low level socket timeouts for client operations.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ClientExamples.java|timeouts}}
```
## Configuring an HTTP Proxy
The following example shows how to configure the use of an HTTP proxy in the client.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ClientExamples.java|proxy}}
```
## Using OkHttp instead of Apache HttpClient
As of HAPI FHIR 2.0, an alternate client implementation is available. This client replaces the low-level Apache HttpClient implementation with the Square [OkHttp](http://square.github.io/okhttp/) library.
Changing HTTP implementations should be mostly ransparent (it has no effect on the actual FHIR semantics which are transmitted over the wire) but might be useful if you have an application that uses OkHttp in other parts of the application and has specific configuration for that library.
Note that as of HAPI FHIR 2.1, OkHttp is the default provider on Android, and will be used without any configuration being required. This is done because HttpClient is deprecated on Android and has caused problems in the past.
To use OkHttp, first add the library as a dependency to your project POM:
```xml
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-client-okhttp</artifactId>
<version>${hapi_stable_version}</version>
</dependency>
```
Then, set the client factory to use OkHttp.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ClientExamples.java|okhttp}}
```

View File

@ -0,0 +1,106 @@
# Client Examples
This page contains examples of how to use the client to perform complete tasks. If you have an example you could contribute, we'd love to hear from you!
# Transaction With Placeholder IDs
The following example shows how to post a transaction with two resources, where one resource contains a reference to the other. A temporary ID (a UUID) is used as an ID to refer to, and this ID will be replaced by the server by a permanent ID.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ClientTransactionExamples.java|conditional}}
```
This code creates the following transaction bundle:
<!-- FIXME: switch to JSON -->
```xml
<Bundle xmlns="http://hl7.org/fhir">
<type value="transaction"/>
<entry>
<fullUrl value="urn:uuid:47709cc7-b3ec-4abc-9d26-3df3d3d57907"/>
<resource>
<Patient xmlns="http://hl7.org/fhir">
<identifier>
<system value="http://acme.org/mrns"/>
<value value="12345"/>
</identifier>
<name>
<family value="Jameson"/>
<given value="J"/>
<given value="Jonah"/>
</name>
<gender value="male"/>
</Patient>
</resource>
<request>
<method value="POST"/>
<url value="Patient"/>
<ifNoneExist value="identifier=http://acme.org/mrns|12345"/>
</request>
</entry>
<entry>
<resource>
<Observation xmlns="http://hl7.org/fhir">
<status value="final"/>
<code>
<coding>
<system value="http://loinc.org"/>
<code value="789-8"/>
<display value="Erythrocytes [#/volume] in Blood by Automated count"/>
</coding>
</code>
<subject>
<reference value="urn:uuid:47709cc7-b3ec-4abc-9d26-3df3d3d57907"/>
</subject>
<valueQuantity>
<value value="4.12"/>
<unit value="10 trillion/L"/>
<system value="http://unitsofmeasure.org"/>
<code value="10*12/L"/>
</valueQuantity>
</Observation>
</resource>
<request>
<method value="POST"/>
<url value="Observation"/>
</request>
</entry>
</Bundle>
```
The server responds with the following response. Note that the ID of the already existing patient is returned, and the ID of the newly created Observation is too.
```xml
<Bundle xmlns="http://hl7.org/fhir">
<id value="dd1f75b8-e472-481e-97b3-c5eebb99a5e0"/>
<type value="transaction-response"/>
<link>
<relation value="self"/>
<url value="http://fhirtest.uhn.ca/baseDstu2"/>
</link>
<entry>
<response>
<status value="200 OK"/>
<location value="Patient/966810/_history/1"/>
<etag value="1"/>
<lastModified value="2015-10-29T07:25:42.465-04:00"/>
</response>
</entry>
<entry>
<response>
<status value="201 Created"/>
<location value="Observation/966828/_history/1"/>
<etag value="1"/>
<lastModified value="2015-10-29T07:33:28.047-04:00"/>
</response>
</entry>
</Bundle>```
# Fetch all Pages of a Bundle
This following example shows how to load all pages of a bundle by fetching each page one-after-the-other and then joining the resuts.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/BundleFetcher.java|loadAll}}
```

View File

@ -0,0 +1,326 @@
# Generic (Fluent) Client
Creating a generic client simply requires you to create an instance of `FhirContext` and use that to instantiate a client.
The following example shows how to create a client, and a few operations which can be performed.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|simple}}
```
<p class="doc_info_bubble">
<b>Performance Tip:</b> Note that FhirContext is an expensive object to create, so you should try to keep an instance around for the lifetime of your application. It is thread-safe so it can be passed as needed. Client instances, on the other hand, are very inexpensive to create so you can create a new one for each request if needed (although there is no requirement to do so, clients are reusable and thread-safe as well).
</p>
# Fluent Calls
The generic client supports queries using a fluent interface which is originally inspired by the excellent [.NET FHIR API](http://firely-team.github.io/fhir-net-api/client-search.html).
The fluent interface allows you to construct powerful queries by chaining method calls together, leading to highly readable code. It also allows you to take advantage of intellisense/code completion in your favourite IDE.
Note that most fluent operations end with an `execute()` statement which actually performs the invocation. You may also invoke several configuration operations just prior to the execute() statement, such as `encodedJson()` or `encodedXml()`.
# Search
Searching is a very powerful part of the FHIR API specification itself, and HAPI FHIR aims to proide a complete implementation of the FHIR API search specification via the generic client API.
## Search - By Type
Searching for resources is probably the most common initial scenario for client applications, so we'll start the demonstration there. The FHIR search operation generally uses a URL with a set of predefined search parameters, and returns a Bundle containing zero-or-more resources which matched the given search criteria.
Search is a very powerful mechanism, with advanced features such as paging, including linked resources, etc. See the FHIR [search specification](http://hl7.org/fhir/search.html) for more information.
The following example shows how to query using the generic client:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|search}}
```
## Search - Multi-valued Parameters (ANY/OR)
To search for a set of possible values where *ANY* should be matched, you can provide multiple values to a parameter, as shown in the example below.
This leads to a URL resembling `http://base/Patient?family=Smith,Smyth`.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|searchOr}}
```
## Search - Multi-valued Parameters (ALL/AND)
To search for a set of possible values where *ALL* should be matched, you can provide multiple instances of a parameter, as shown in the example below.
This leads to a URL resembling `http://base/Patient?address=Toronto&address=Ontario&address=Canada`.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|searchAnd}}
```
## Search - Paging
If the server supports paging results, the client has a page method which can be used to load subsequent pages.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|searchPaging}}
```
## Search - Composite Parameters
If a composite parameter is being searched on, the parameter takes a "left" and "right" operand, each of which is a parameter from the resource being seached. The following example shows the syntax.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|searchComposite}}
```
## Search - By plain URL
You can also perform a search using a String URL, instead of using the fluent method calls to build the URL. This can be useful if you have a URL you retrieved from somewhere else that you want to use as a search.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|searchUrl}}
```
## Search - Other Query Options
The fluent search also has methods for sorting, limiting, specifying JSON encoding, _include, _revinclude, _lastUpdated, _tag, etc.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|searchAdv}}
```
## Search - Using HTTP POST
The FHIR specification allows the use of an HTTP POST to transmit a search to a server instead of using
an HTTP GET. With this style of search, the search parameters are included in the request body instead
of the request URL, which can be useful if you need to transmit a search with a large number of parameters.
The [`usingStyle(SearchStyleEnum)`](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/gclient/IQuery.html#usingStyle(ca.uhn.fhir.rest.api.SearchStyleEnum)) method controls which style to use. By default, GET style is used unless the client detects that the request would result in a very long URL (over 8000 chars) in which case the client automatically switches to POST.
If you wish to force the use of HTTP POST, you can do that as well.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|searchPost}}
```
## Search - Compartments
To search a [resource compartment](http://www.hl7.org/implement/standards/fhir/extras.html#compartment), simply use the [`withIdAndCompartment()`](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/gclient/IQuery.html#withIdAndCompartment(java.lang.String,java.lang.String)) method in your search.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|searchCompartment}}
```
## Search - Subsetting (_summary and _elements)
Sometimes you may want to only ask the server to include some parts of returned resources (instead of the whole resource). Typically this is for performance or optimization reasons, but there may also be privacy reasons for doing this.
To request that the server return only "summary" elements (those elements defined in the specification with the "Σ" flag), you can use the [`summaryMode(SummaryEnum)`](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/gclient/IClientExecutable.html#summaryMode(ca.uhn.fhir.rest.api.SummaryEnum)) qualifier:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|searchSubsetSummary}}
```
To request that the server return only elements from a custom list provided by the client, you can use the [`elementsSubset(String...)`](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/gclient/IClientExecutable.html#elementsSubset(java.lang.String...)) qualifier:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|searchSubsetElements}}
```
# Create - Type
The following example shows how to perform a create operation using the generic client:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|create}}
```
## Conditional Creates
FHIR also specifies a type of update called "conditional create", where a set of search parameters are provided and a new resource is only created if no existing resource matches those parameters. See the FHIR specification for more information on conditional creation.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|createConditional}}
```
# Read/VRead - Instance
Given a resource name and ID, it is simple to retrieve the latest version of that resource (a 'read').
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|read}}
```
By adding a version string, it is also possible to retrieve a specific version (a 'vread').
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|vread}}
```
It is also possible to retrieve a resource given its absolute URL (this will override the base URL set on the client).
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|readabsolute}}
```
**See Also:** See the description of [Read/VRead ETags](#read_etags) below for information on specifying a matching version in the client request.
# Delete - Instance
The following example shows how to perform a delete operation using the generic client:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|delete}}
```
## Conditional Deletes
Conditional deletions are also possible, which is a form where instead of deleting a resource using its logical ID, you specify a set of search criteria and a single resource is deleted if it matches that criteria. Note that this is not a mechanism for bulk deletion; see the FHIR specification for information on conditional deletes and how they are used.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|deleteConditional}}
```
# Update - Instance
Updating a resource is similar to creating one, except that an ID must be supplied since you are updating a previously existing resource instance.
The following example shows how to perform an update operation using the generic client:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|update}}
```
## Conditional Updates
FHIR also specifies a type of update called "conditional updates", where insetad of using the logical ID of a resource to update, a set of search parameters is provided. If a single resource matches that set of parameters, that resource is updated. See the FHIR specification for information on how conditional updates work.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|updateConditional}}
```
**See Also:** See the description of [Update ETags](#update_etags) below for information on specifying a matching version in the client request.
# History - Server/Type/Instance
To retrieve the version history of all resources, or all resources of a given type, or of a specific instance of a resource, you call the [`history()`](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/client/api/IGenericClient.html#history()) method.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|historyDstu2}}
```
You can also optionally request that only resource versions later than a given date, and/or only up to a given count (number) of resource versions be returned.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|historyFeatures}}
```
# Transaction - Server
The following example shows how to execute a transaction using the generic client:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|transaction}}
```
# Capability Statement (metadata) - Server
To retrieve the server's capability statement, simply call the [`capabilities()`](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/client/api/IGenericClient.html#capabilities()) method as shown below.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|conformance}}
```
# Extended Operations
FHIR also supports a set of *extended operatioons*, which are operatons beyond the basic CRUD operations defined in the specificiation. These operations are an RPC style of invocation, with a set of named input parameters passed to the server and a set of named output parameters returned back.
To invoke an operation using the client, you simply need to create the input [Parameters](/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/Parameters.html) resource, then pass that to the [`operation()`](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/client/api/IGenericClient.html#operation()) fluent method.
The example below shows a simple operation call.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|operation}}
```
Note that if the operation does not require any input parameters, you may also invoke the operation using the following form. Note that the `withNoParameters` form still requires you to provide the type of the Parameters resource so that it can return the correct type in the response.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|operationNoIn}}
```
## Using the HTTP GET Form
By default, the client will invoke operations using the HTTP POST form. The FHIR specification also allows requests to use the HTTP GET verb if the operation does not affect state and has no composite/resource parameters. Use the following form to invoke operation with HTTP GET.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|operationHttpGet}}
```
## Built-In Operations - Validate
The `$validate` operation asks the server to test a given resource to see if it would be acceptable as a create/update on that server. The client has built-in support for this operation.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|validate}}
```
# Built-In Operations - Process-Message
The `$process-message` operation asks the server to accept a FHIR message bundle for processing.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ClientExamples.java|processMessage}}
```
# Additional Properties
This section contains ways of customizing the request sent by the client.
## Cache-Control
The `Cache-Control` header can be used by the client in a request to signal to the server (or any cache in front of it) that the client wants specific behaviour from the cache, or wants the cache to not act on the request altogether. Naturally, not all servers will honour this header.
To add a cache control directive in a request:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ClientExamples.java|cacheControl}}
```
<a name="etags"/>
# ETags
ETag features are added simply by adding fluent method calls to the client method chain, as shown in the following examples.
<a name="read_etags"/>
## Read / VRead ETags
To notify the server that it should return an `HTTP 304 Not Modified` if the content has not changed, add an [`ifVersionMatches()`](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/gclient/IReadExecutable.html#ifVersionMatches(java.lang.String)) invocation.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|etagread}}
```
This method will add the following header to the request:
```http
If-None-Match: "W/001"
```
<a name="update_etags"/>
## Update ETags
To implement version aware updates, specify a version in the request. This will notify the server that it should only update the resource on the server if the version matches the given version. This is useful to prevent two clients from attempting to modify the resource at the same time, and having one client's updates overwrite the other's.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/GenericClientExample.java|etagupdate}}
```
The following header will be added to the request as a part of this interaction:
```http
If-Match: "W/001"
```

View File

@ -0,0 +1,5 @@
# Getting Started with the Client
A starter project containing all nedded dependencies and some starter code for the HAPI FHIR client is available here:
* [hapi-fhirstarters-client-skeleton](https://github.com/FirelyTeam/fhirstarters/tree/master/java/hapi-fhirstarters-client-skeleton/)

View File

@ -0,0 +1,13 @@
# Client Introduction
HAPI FHIR provides a built-in mechanism for connecting to FHIR REST servers.
The HAPI RESTful client is designed to be easy to set up and to allow strong compile-time type checking wherever possible.
There are two types of REST clients provided by HAPI:
* The [Generic (Fluent) client](./generic_client.html) is designed to be very flexible, yet easy to use. It allows you to build up FHIR REST invocations using a fluent API that is consistent and powerful. If you are getting started with HAPI FHIR and aren't sure which client to use, this is the client to start with.
* The [Annotation Client](./annotation_client.html) client relies on static binding to specific operations to give better compile-time checking against servers with a specific set of capabilities
exposed. This second model takes more effort to use, but can be useful if the person defining the specific methods to invoke is not the same person who is using those methods.

View File

@ -79,13 +79,13 @@ If the build fails to execute successfully, try the following:
Import the HAPI projects as Maven Modules by selecting **File -&gt; Import...** from the File menu. Then select **Existing Module Projects** as shown below.
<img src="../../images/hacking_import.png"/>
<img src="/hapi-fhir/docs/images/hacking_import.png"/>
**Select the Projects**
Next, browse to the directory where you checked out the HAPI FHIR sources. You might want to select only the projects you are interested in editing, in order to keep Eclipse's memory use down. You can always come back and import more later.
<img src="../../images/hacking_import_step2.png"/>
<img src="/hapi-fhir/docs/images/hacking_import_step2.png"/>
## Troubleshooting

View File

@ -1,6 +1,7 @@
section.introduction.title=Welcome to HAPI FHIR
page.introduction.table_of_contents=Table of Contents
page.introduction.changelog=Changelog
page.introduction.introduction=Introduction
page.introduction.versions=FHIR and HAPI FHIR Versions
page.introduction.modules=HAPI FHIR Modules
@ -8,11 +9,20 @@ page.introduction.downloading_and_importing=Downloading and Importing
section.model.title=Working With The FHIR Model
page.model.working_with_resources=Working With Resources
page.model.references=Resource References
page.model.profiles_and_extensions=Profiles and Extensions
page.model.converter=Version Converters
page.model.custom_structures=Custom Structures
page.model.narrative_generation=Narrative Generation
section.client.title=Client
page.client.introduction=Introduction
page.client.generic_client=Generic (Fluent) Client
page.client.annotation_client=Annotation Client
page.client.client_configuration=Client Configuration
page.client.get_started=Get Started
page.client.examples=Client Examples
section.server_plain.title=Plain Server
page.server_plain.server_types=REST Server Types
page.server_plain.introduction=Plain Server Introduction
@ -20,19 +30,25 @@ page.server_plain.get_started=Getting Started with Plain Server
page.server_plain.resource_providers=Resource Providers and Plan Providers
page.server_plain.rest_operations=REST Operations: Overview
page.server_plain.rest_operations_search=REST Operations: Search
page.server_plain.rest_operations_operations=REST Operations: Operations Framework
page.server_plain.rest_operations_operations=REST Operations: Extended Operations
page.server_plain.paging=Paging Search Results
page.server_plain.cors=CORS
page.server_plain.web_testpage_overlay=Web Testpage Overlay
page.server_plain.multitenency=Multitenency
page.server_plain.jax_rs=JAX-RS Support
section.server_jpa.title=JPA Server
section.server_jpa.introduction=Introduction
section.server_jpa.get_started=Get Started
section.server_jpa.architecture=Architecture
section.server_jpa.upgrading=Upgrade Guide
page.server_jpa.introduction=Introduction
page.server_jpa.get_started=Get Started
page.server_jpa.architecture=Architecture
page.server_jpa.upgrading=Upgrade Guide
section.interceptors.title=Interceptors
page.interceptors.interceptors=Interceptors Overview
page.interceptors.client_interceptors=Client Interceptors
page.interceptors.built_in_client_interceptors=Built-In Client Interceptors
page.interceptors.server_interceptors=Server Interceptors
page.interceptors.built_in_server_interceptors=Built-In Server Interceptors
section.security.title=Security
page.security.introduction=Introduction
@ -41,7 +57,11 @@ page.security.consent_interceptor=Consent Interceptor
page.security.narrowing_interceptor=Narrowing Interceptor
section.validation.title=Validation
section.validation.examples=Validation Examples
page.validation.introduction=Introduction
page.validation.parser_error_handler=Parser Error Handler
page.validation.profile_validator=Profile Validator
page.validation.schema_validator=Schema/Schematron Validator
page.validation.examples=Validation Examples
section.android.title=Android
page.android.client=Android Client
@ -54,5 +74,4 @@ page.contributing.hacking_guide=Hacking Guide
section.appendix.title=Appendix
page.appendix.logging=Logging
page.appendix.changelog=Changelog
page.appendix.faq=FAQ

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="614px" height="153px" version="1.1"><defs/><g transform="translate(0.5,0.5)"><path d="M 17 1 L 121 1 L 121 61 L 17 61 L 17 49 L 1 49 L 1 37 L 17 37 L 17 25 L 1 25 L 1 13 L 17 13 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 17 13 L 33 13 L 33 25 L 17 25 M 17 37 L 33 37 L 33 49 L 17 49" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g fill="#000000" font-family="Helvetica" font-size="12px"><text x="39" y="35">hapi-fhir</text></g><rect x="321" y="1" width="110" height="60" rx="9" ry="9" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(323,24)"><switch><foreignObject pointer-events="all" width="106" height="15" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 106px; white-space: normal; text-align: center;">slf4j-api</div></foreignObject><text x="53" y="14" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><path d="M 121 31 L 315 31" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 320 31 L 313 35 L 315 31 L 313 28 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 67 91 L 171 91 L 171 151 L 67 151 L 67 139 L 51 139 L 51 127 L 67 127 L 67 115 L 51 115 L 51 103 L 67 103 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 67 103 L 83 103 L 83 115 L 67 115 M 67 127 L 83 127 L 83 139 L 67 139" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g fill="#000000" font-family="Helvetica" font-size="12px"><text x="89" y="118">commons-</text><text x="89" y="132">httpclient</text></g><rect x="221" y="91" width="110" height="60" rx="9" ry="9" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(223,114)"><switch><foreignObject pointer-events="all" width="106" height="15" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 106px; white-space: normal; text-align: center;">jcl-over-slf4j</div></foreignObject><text x="53" y="14" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><path d="M 91 61 L 107 86" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 110 90 L 104 86 L 107 86 L 109 82 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 171 121 L 215 121" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 220 121 L 213 125 L 215 121 L 213 118 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 309 91 L 338 65" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 342 62 L 339 69 L 338 65 L 334 64 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 441 36 L 441 26 L 461 26 L 461 16 L 491 31 L 461 46 L 461 36 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><rect x="501" y="11" width="80" height="40" fill="none" stroke="none" pointer-events="none"/><g fill="#000000" font-family="Helvetica" font-size="12px"><text x="503" y="14">Underlying </text><text x="503" y="28">Logging</text><text x="503" y="42">Framework</text><text x="503" y="56">(logback, log4j, etc.)</text></g></g></svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,594 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="672px" height="468px" version="1.1">
<defs>
<linearGradient x1="0%" y1="0%" x2="0%" y2="100%"
id="mx-gradient-fff2cc-1-ffd966-1-s-0">
<stop offset="0%" style="stop-color:#FFF2CC" />
<stop offset="100%" style="stop-color:#FFD966" />
</linearGradient>
<linearGradient x1="0%" y1="0%" x2="0%" y2="100%"
id="mx-gradient-ffffff-0.9-ffffff-0.1-s-0">
<stop offset="0%" style="stop-color:#ffffff;stop-opacity:0.9" />
<stop offset="100%" style="stop-color:#ffffff;stop-opacity:0.1" />
</linearGradient>
<linearGradient x1="0%" y1="0%" x2="0%" y2="100%"
id="mx-gradient-d5e8d4-1-97d077-1-s-0">
<stop offset="0%" style="stop-color:#D5E8D4" />
<stop offset="100%" style="stop-color:#97D077" />
</linearGradient>
<linearGradient x1="0%" y1="0%" x2="0%" y2="100%"
id="mx-gradient-f5f5f5-1-b3b3b3-1-s-0">
<stop offset="0%" style="stop-color:#F5F5F5" />
<stop offset="100%" style="stop-color:#B3B3B3" />
</linearGradient>
</defs>
<g transform="translate(0.5,0.5)">
<rect x="211" y="246" width="98" height="90" rx="13.5" ry="13.5"
fill="#ffffff" stroke="#000000" pointer-events="none" />
<rect x="213" y="248" width="94" height="86" rx="12.9" ry="12.9"
fill="#ffffff" stroke="#000000" pointer-events="none" />
<g transform="translate(213,277)">
<switch>
<foreignObject pointer-events="all" width="93" height="32"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 91px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
External FHIR Clients
<br />
</div></div></foreignObject>
<text x="47" y="22" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<rect x="211" y="127" width="195" height="90" fill="#a9c4eb"
stroke="#808080" stroke-width="2" pointer-events="none" />
<g transform="translate(184,172)rotate(-90,35.5,0)">
<switch>
<foreignObject pointer-events="all" width="71" height="32"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 71px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
Your
<br />
<div align="left">Application</div>
</div></div></foreignObject>
<text x="36" y="22" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<rect x="361" y="147" width="70" height="50" rx="7.5" ry="7.5"
fill="#d0d0d0" stroke="#d0d0d0" transform="translate(2,3)" opacity="1" />
<rect x="361" y="147" width="70" height="50" rx="7.5" ry="7.5"
fill="url(#mx-gradient-fff2cc-1-ffd966-1-s-0)" stroke="#d6b656"
pointer-events="none" />
<path
d="M 369.65 146 Q 360 146 360 155.65 L 360 167 Q 396 182 432 167 L 432 155.65 Q 432 146 422.35 146 Z"
fill="url(#mx-gradient-ffffff-0.9-ffffff-0.1-s-0)" stroke="none"
pointer-events="none" />
<g transform="translate(360,158)">
<switch>
<foreignObject pointer-events="all" width="71" height="32"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 71px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
HAPI FHIR
<br />
Client
<br />
</div></div></foreignObject>
<text x="36" y="22" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<rect x="281" y="147" width="70" height="50" rx="7.5" ry="7.5"
fill="#d0d0d0" stroke="#d0d0d0" transform="translate(2,3)" opacity="1" />
<rect x="281" y="147" width="70" height="50" rx="7.5" ry="7.5"
fill="url(#mx-gradient-fff2cc-1-ffd966-1-s-0)" stroke="#d6b656"
pointer-events="none" />
<path
d="M 289.65 146 Q 280 146 280 155.65 L 280 167 Q 316 182 352 167 L 352 155.65 Q 352 146 342.35 146 Z"
fill="url(#mx-gradient-ffffff-0.9-ffffff-0.1-s-0)" stroke="none"
pointer-events="none" />
<g transform="translate(289,150)">
<switch>
<foreignObject pointer-events="all" width="53" height="47"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 53px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
HAPI
<br />
Model
<br />
Objects
</div></div></foreignObject>
<text x="27" y="30" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<rect x="521" y="127" width="120" height="90" rx="13.5" ry="13.5"
fill="#ffffff" stroke="#000000" pointer-events="none" />
<rect x="523" y="129" width="116" height="86" rx="12.9" ry="12.9"
fill="#ffffff" stroke="#000000" pointer-events="none" />
<g transform="translate(553,150)">
<switch>
<foreignObject pointer-events="all" width="56" height="47"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 56px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
External
<br />
FHIR
<br />
Server
<br />
</div></div></foreignObject>
<text x="28" y="30" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<path
d="M 441.5 180.5 L 441.5 161.5 L 488.26 161.5 L 488.26 150 L 510.5 171 L 488.26 192 L 488.26 180.5 Z"
fill="#ff9999" stroke="#000000" stroke-linejoin="round"
stroke-miterlimit="10" pointer-events="none" />
<g transform="translate(461,165)">
<switch>
<foreignObject pointer-events="all" width="31" height="16"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; white-space: nowrap; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">HTTP</div></div></foreignObject>
<text x="16" y="14" fill="#000000" text-anchor="middle"
font-size="11px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<path
d="M 191 116 L 184.88 116 Q 178.75 116 178.75 126 L 178.75 161 Q 178.75 171 169.88 171 L 165.44 171 Q 161 171 169.88 171 L 174.31 171 Q 178.75 171 178.75 181 L 178.75 216 Q 178.75 226 184.88 226 L 191 226"
fill="none" stroke="#999999" stroke-miterlimit="10" pointer-events="none" />
<rect x="1" y="126" width="150" height="90" fill="none" stroke="none"
pointer-events="none" />
<g transform="translate(3,134)">
<switch>
<foreignObject pointer-events="all" width="146"
height="78" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(77, 77, 77); line-height: 1.26; vertical-align: top; overflow: hidden; max-height: 86px; max-width: 146px; width: 146px; white-space: normal; text-align: right;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
Use the HAPI FHIR client in an application to fetch from or store
resources to an external server.
<br />
<a href="/doc_rest_client.html">Learn Mode</a>
</div></div></foreignObject>
<text x="73" y="45" fill="#4D4D4D" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<rect x="421" y="246" width="230" height="90" fill="#a9c4eb"
stroke="#808080" stroke-width="2" pointer-events="none" />
<g transform="translate(611,262)rotate(-90,35.5,29)">
<switch>
<foreignObject pointer-events="all" width="71" height="32"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 71px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
Your
<br />
<div align="left">Application</div>
</div></div></foreignObject>
<text x="36" y="22" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<rect x="486" y="266" width="70" height="50" rx="7.5" ry="7.5"
fill="#d0d0d0" stroke="#d0d0d0" transform="translate(2,3)" opacity="1" />
<rect x="486" y="266" width="70" height="50" rx="7.5" ry="7.5"
fill="url(#mx-gradient-fff2cc-1-ffd966-1-s-0)" stroke="#d6b656"
pointer-events="none" />
<path
d="M 494.65 265 Q 485 265 485 274.65 L 485 286 Q 521 301 557 286 L 557 274.65 Q 557 265 547.35 265 Z"
fill="url(#mx-gradient-ffffff-0.9-ffffff-0.1-s-0)" stroke="none"
pointer-events="none" />
<g transform="translate(494,269)">
<switch>
<foreignObject pointer-events="all" width="53" height="47"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 53px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
HAPI
<br />
Model
<br />
Objects
</div></div></foreignObject>
<text x="27" y="30" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<rect x="396" y="266" width="70" height="50" rx="7.5" ry="7.5"
fill="#d0d0d0" stroke="#d0d0d0" transform="translate(2,3)" opacity="1" />
<rect x="396" y="266" width="70" height="50" rx="7.5" ry="7.5"
fill="url(#mx-gradient-fff2cc-1-ffd966-1-s-0)" stroke="#d6b656"
pointer-events="none" />
<path
d="M 404.65 265 Q 395 265 395 274.65 L 395 286 Q 431 301 467 286 L 467 274.65 Q 467 265 457.35 265 Z"
fill="url(#mx-gradient-ffffff-0.9-ffffff-0.1-s-0)" stroke="none"
pointer-events="none" />
<g transform="translate(395,277)">
<switch>
<foreignObject pointer-events="all" width="71" height="32"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 71px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
HAPI FHIR
<br />
Server
</div></div></foreignObject>
<text x="36" y="22" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<path
d="M 316.5 299.5 L 316.5 280.5 L 363.26 280.5 L 363.26 269 L 385.5 290 L 363.26 311 L 363.26 299.5 Z"
fill="#ff9999" stroke="#000000" stroke-linejoin="round"
stroke-miterlimit="10" pointer-events="none" />
<g transform="translate(336,284)">
<switch>
<foreignObject pointer-events="all" width="31" height="16"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; white-space: nowrap; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">HTTP</div></div></foreignObject>
<text x="16" y="14" fill="#000000" text-anchor="middle"
font-size="11px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<path
d="M 191 236 L 184.88 236 Q 178.75 236 178.75 246 L 178.75 281 Q 178.75 291 169.88 291 L 165.44 291 Q 161 291 169.88 291 L 174.31 291 Q 178.75 291 178.75 301 L 178.75 336 Q 178.75 346 184.88 346 L 191 346"
fill="none" stroke="#999999" stroke-miterlimit="10" pointer-events="none" />
<rect x="1" y="236" width="150" height="110" fill="none" stroke="none"
pointer-events="none" />
<g transform="translate(3,247)">
<switch>
<foreignObject pointer-events="all" width="146"
height="93" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(77, 77, 77); line-height: 1.26; vertical-align: top; overflow: hidden; max-height: 106px; max-width: 146px; width: 146px; white-space: normal; text-align: right;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
Use the HAPI FHIR server in an application to allow external
applications to access or modify your application's data.
<br />
<a href="/doc_rest_server.html">Learn More</a>
<br />
</div></div></foreignObject>
<text x="73" y="53" fill="#4D4D4D" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<rect x="424" y="366" width="227" height="90" fill="#99ff99"
stroke="#808080" stroke-width="2" pointer-events="none" />
<g transform="translate(603,367)rotate(-90,44,44)">
<switch>
<foreignObject pointer-events="all" width="88" height="47"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 86px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
HAPI JPA Database Server
<br />
</div></div></foreignObject>
<text x="44" y="30" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<rect x="396" y="386" width="70" height="50" rx="7.5" ry="7.5"
fill="#d0d0d0" stroke="#d0d0d0" transform="translate(2,3)" opacity="1" />
<rect x="396" y="386" width="70" height="50" rx="7.5" ry="7.5"
fill="url(#mx-gradient-fff2cc-1-ffd966-1-s-0)" stroke="#d6b656"
pointer-events="none" />
<path
d="M 404.65 385 Q 395 385 395 394.65 L 395 406 Q 431 421 467 406 L 467 394.65 Q 467 385 457.35 385 Z"
fill="url(#mx-gradient-ffffff-0.9-ffffff-0.1-s-0)" stroke="none"
pointer-events="none" />
<g transform="translate(396,397)">
<switch>
<foreignObject pointer-events="all" width="69" height="32"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 67px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
HAPI FHIR Server
<br />
</div></div></foreignObject>
<text x="35" y="22" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<rect x="481" y="386" width="70" height="50" rx="7.5" ry="7.5"
fill="#d0d0d0" stroke="#d0d0d0" transform="translate(2,3)" opacity="1" />
<rect x="481" y="386" width="70" height="50" rx="7.5" ry="7.5"
fill="url(#mx-gradient-fff2cc-1-ffd966-1-s-0)" stroke="#d6b656"
pointer-events="none" />
<path
d="M 489.65 385 Q 480 385 480 394.65 L 480 406 Q 516 421 552 406 L 552 394.65 Q 552 385 542.35 385 Z"
fill="url(#mx-gradient-ffffff-0.9-ffffff-0.1-s-0)" stroke="none"
pointer-events="none" />
<g transform="translate(481,389)">
<switch>
<foreignObject pointer-events="all" width="69" height="47"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 67px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
JPA Persistence Module
<br />
</div></div></foreignObject>
<text x="35" y="30" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<rect x="211" y="366" width="110" height="90" fill="#a9c4eb"
stroke="#808080" stroke-width="2" pointer-events="none" />
<g transform="translate(230,397)">
<switch>
<foreignObject pointer-events="all" width="71" height="32"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 71px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
Your
<br />
<div align="left">Application</div>
</div></div></foreignObject>
<text x="36" y="22" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<path
d="M 331.5 419.5 L 331.5 400.5 L 368.26 400.5 L 368.26 389 L 390.5 410 L 368.26 431 L 368.26 419.5 Z"
fill="#ff9999" stroke="#000000" stroke-linejoin="round"
stroke-miterlimit="10" pointer-events="none" />
<g transform="translate(346,404)">
<switch>
<foreignObject pointer-events="all" width="31" height="16"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; white-space: nowrap; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">HTTP</div></div></foreignObject>
<text x="16" y="14" fill="#000000" text-anchor="middle"
font-size="11px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<path
d="M 191 356 L 184.88 356 Q 178.75 356 178.75 366 L 178.75 401 Q 178.75 411 169.88 411 L 165.44 411 Q 161 411 169.88 411 L 174.31 411 Q 178.75 411 178.75 421 L 178.75 456 Q 178.75 466 184.88 466 L 191 466"
fill="none" stroke="#999999" stroke-miterlimit="10" pointer-events="none" />
<rect x="1" y="356" width="150" height="110" fill="none" stroke="none"
pointer-events="none" />
<g transform="translate(3,360)">
<switch>
<foreignObject pointer-events="all" width="146"
height="106" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(77, 77, 77); line-height: 1.26; vertical-align: top; overflow: hidden; max-height: 106px; max-width: 146px; width: 146px; white-space: normal; text-align: right;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
Use the HAPI JPA/Database Server to deploy a fully functional FHIR
server you can develop applications against.
<br />
<a href="/doc_jpa.html">Learn More</a>
</div></div></foreignObject>
<text x="73" y="59" fill="#4D4D4D" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<rect x="211" y="9" width="440" height="90" fill="#a9c4eb"
stroke="#808080" stroke-width="2" pointer-events="none" />
<g transform="translate(184,54)rotate(-90,35.5,0)">
<switch>
<foreignObject pointer-events="all" width="71" height="32"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 71px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
Your
<br />
<div align="left">Application</div>
</div></div></foreignObject>
<text x="36" y="22" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<rect x="266" y="29" width="55" height="50" rx="7.5" ry="7.5"
fill="#d0d0d0" stroke="#d0d0d0" transform="translate(2,3)" opacity="1" />
<rect x="266" y="29" width="55" height="50" rx="7.5" ry="7.5"
fill="url(#mx-gradient-fff2cc-1-ffd966-1-s-0)" stroke="#d6b656"
pointer-events="none" />
<path
d="M 274.65 28 Q 265 28 265 37.65 L 265 49 Q 293.5 64 322 49 L 322 37.65 Q 322 28 312.35 28 Z"
fill="url(#mx-gradient-ffffff-0.9-ffffff-0.1-s-0)" stroke="none"
pointer-events="none" />
<g transform="translate(267,32)">
<switch>
<foreignObject pointer-events="all" width="53" height="47"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 53px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
HAPI
<br />
Model
<br />
Objects
</div></div></foreignObject>
<text x="27" y="30" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<rect x="326" y="29" width="70" height="50" rx="7.5" ry="7.5"
fill="#d0d0d0" stroke="#d0d0d0" transform="translate(2,3)" opacity="1" />
<rect x="326" y="29" width="70" height="50" rx="7.5" ry="7.5"
fill="url(#mx-gradient-fff2cc-1-ffd966-1-s-0)" stroke="#d6b656"
pointer-events="none" />
<path
d="M 334.65 28 Q 325 28 325 37.65 L 325 49 Q 361 64 397 49 L 397 37.65 Q 397 28 387.35 28 Z"
fill="url(#mx-gradient-ffffff-0.9-ffffff-0.1-s-0)" stroke="none"
pointer-events="none" />
<g transform="translate(326,32)">
<switch>
<foreignObject pointer-events="all" width="69" height="47"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 67px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
HAPI FHIR
<br />
Parser (Xml/Json)
<br />
</div></div></foreignObject>
<text x="35" y="30" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<path
d="M 401.5 61.33 L 401.5 46.67 L 408.66 46.67 L 408.66 37.06 L 420.5 54 L 408.66 70.94 L 408.66 61.33 Z"
fill="none" stroke="#000000" stroke-linejoin="round"
stroke-miterlimit="10" pointer-events="none" />
<g transform="translate(410,43)">
<switch>
<foreignObject pointer-events="all" width="2" height="16"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; white-space: nowrap; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml"><br /></div></div></foreignObject>
<text x="1" y="14" fill="#000000" text-anchor="middle"
font-size="11px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<path d="M 454 24 L 484 24 L 484 84 L 424 84 L 424 54 Z" fill="none"
stroke="#000000" stroke-miterlimit="10" pointer-events="none" />
<g transform="translate(423,51)">
<switch>
<foreignObject pointer-events="all" width="61" height="32"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 59px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
Raw FHIR Resources
<br />
</div></div></foreignObject>
<text x="31" y="22" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<path d="M 450 30 L 482 30 L 482 50 L 450 50 Z" fill="url(#mx-gradient-d5e8d4-1-97d077-1-s-0)"
stroke="#82b366" stroke-miterlimit="10" pointer-events="none" />
<path d="M 450 30 L 466 40 L 482 30" fill="none" stroke="#82b366"
stroke-miterlimit="10" pointer-events="none" />
<rect x="510" y="29" width="70" height="50" rx="7.5" ry="7.5"
fill="#d0d0d0" stroke="#d0d0d0" transform="translate(2,3)" opacity="1" />
<rect x="510" y="29" width="70" height="50" rx="7.5" ry="7.5"
fill="url(#mx-gradient-fff2cc-1-ffd966-1-s-0)" stroke="#d6b656"
pointer-events="none" />
<path
d="M 518.65 28 Q 509 28 509 37.65 L 509 49 Q 545 64 581 49 L 581 37.65 Q 581 28 571.35 28 Z"
fill="url(#mx-gradient-ffffff-0.9-ffffff-0.1-s-0)" stroke="none"
pointer-events="none" />
<g transform="translate(510,32)">
<switch>
<foreignObject pointer-events="all" width="69" height="47"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 67px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
HAPI FHIR
<br />
Parser (Xml/Json)
<br />
</div></div></foreignObject>
<text x="35" y="30" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<rect x="586" y="29" width="55" height="50" rx="7.5" ry="7.5"
fill="#d0d0d0" stroke="#d0d0d0" transform="translate(2,3)" opacity="1" />
<rect x="586" y="29" width="55" height="50" rx="7.5" ry="7.5"
fill="url(#mx-gradient-fff2cc-1-ffd966-1-s-0)" stroke="#d6b656"
pointer-events="none" />
<path
d="M 594.65 28 Q 585 28 585 37.65 L 585 49 Q 613.5 64 642 49 L 642 37.65 Q 642 28 632.35 28 Z"
fill="url(#mx-gradient-ffffff-0.9-ffffff-0.1-s-0)" stroke="none"
pointer-events="none" />
<g transform="translate(587,32)">
<switch>
<foreignObject pointer-events="all" width="53" height="47"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 53px; white-space: normal; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
HAPI
<br />
Model
<br />
Objects
</div></div></foreignObject>
<text x="27" y="30" fill="#000000" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<path
d="M 489.5 61.33 L 489.5 46.67 L 496.66 46.67 L 496.66 37.06 L 508.5 54 L 496.66 70.94 L 496.66 61.33 Z"
fill="none" stroke="#000000" stroke-linejoin="round"
stroke-miterlimit="10" pointer-events="none" />
<g transform="translate(498,43)">
<switch>
<foreignObject pointer-events="all" width="2" height="16"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; white-space: nowrap; text-align: center;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml"><br /></div></div></foreignObject>
<text x="1" y="14" fill="#000000" text-anchor="middle"
font-size="11px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<path
d="M 191 1 L 184.88 1 Q 178.75 1 178.75 11 L 178.75 44 Q 178.75 54 169.88 54 L 165.44 54 Q 161 54 169.88 54 L 174.31 54 Q 178.75 54 178.75 64 L 178.75 97 Q 178.75 107 184.88 107 L 191 107"
fill="none" stroke="#999999" stroke-miterlimit="10" pointer-events="none" />
<rect x="1" y="9" width="150" height="90" fill="none" stroke="none"
pointer-events="none" />
<g transform="translate(3,17)">
<switch>
<foreignObject pointer-events="all" width="146"
height="78" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml"
style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(77, 77, 77); line-height: 1.26; vertical-align: top; overflow: hidden; max-height: 86px; max-width: 146px; width: 146px; white-space: normal; text-align: right;"><div
style="display:inline-block;text-align:inherit;text-decoration:inherit;"
xmlns="http://www.w3.org/1999/xhtml">
Use the HAPI FHIR parser and encoder to convert between FHIR and
your application's data model.
<br />
<a href="/doc_fhirobjects.html">Learn More</a>
</div></div></foreignObject>
<text x="73" y="45" fill="#4D4D4D" text-anchor="middle"
font-size="12px" font-family="Helvetica">[Not supported by viewer]</text>
</switch>
</g>
<path
d="M 574 279 C 574 268.33 604 268.33 604 279 L 604 303 C 604 313.67 574 313.67 574 303 Z"
fill="url(#mx-gradient-f5f5f5-1-b3b3b3-1-s-0)" stroke="#666666"
stroke-miterlimit="10" pointer-events="none" />
<path d="M 574 279 C 574 287 604 287 604 279" fill="none" stroke="#666666"
stroke-miterlimit="10" pointer-events="none" />
<path
d="M 565 399 C 565 388.33 595 388.33 595 399 L 595 423 C 595 433.67 565 433.67 565 423 Z"
fill="url(#mx-gradient-f5f5f5-1-b3b3b3-1-s-0)" stroke="#666666"
stroke-miterlimit="10" pointer-events="none" />
<path d="M 565 399 C 565 407 595 407 595 399" fill="none" stroke="#666666"
stroke-miterlimit="10" pointer-events="none" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 32 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,3 @@
# Built-In Client Interceptors
<a name="req_resp_logging"/>

View File

@ -0,0 +1,3 @@
# Built-In Server Interceptors
<a name="logging_server_requests"/>

View File

@ -0,0 +1,3 @@
# Client Interceptors
<a name="req_resp_logging"/>

View File

@ -0,0 +1 @@
# Server Interceptors

View File

@ -122,7 +122,7 @@ System.setProperty("javax.xml.stream.XMLEventFactory", "com.ctc.wstx.stax.WstxEv
## PH-Schematron
If you are using the [Schematron Validation](/docs/validation/schema.html) module, you will also need to include the Ph-Schematron library on your classpath. (Note that prior to HAPI FHIR 3.4.0 we used Phloc-Schamtron instead, but that library has been discontinued).
If you are using the [Schematron Validation](/docs/validation/schema_validator.html) module, you will also need to include the Ph-Schematron library on your classpath. (Note that prior to HAPI FHIR 3.4.0 we used Phloc-Schamtron instead, but that library has been discontinued).
If you are using Maven, this library is not added by default (it is marked as an optional dependency) since not all applications need Schematron support. As a result you will need to manually add the following dependencies to your project pom.xml:

View File

@ -9,19 +9,17 @@ HAPI FHIR is based on the same principle, but applied to the Java implementation
# Getting Started
To get started with HAPI FHIR, first download a copy and add it to your project. See the [Download Page](./download.html) for instructions.
To get started with HAPI FHIR, first download a copy and add it to your project. See [Downloading and Importing](./downloading_and_importing.html) for instructions.
## A Note on FHIR Versions
Before discussing HAPI itself, a quick word about FHIR versions. FHIR is not yet a finalized "1.0" standard. It is currently in the DSTU phase, which means that it is changing in subtle and non-subtle ways between releases. Before trying to use FHIR, you will need to determine which version of FHIR you want to support in your application. Typically this would be the latest version, but if you are looking to interact with an application which already exists, you will probably want to implement the same version implemented by that application.
See the [note on DSTU2 support](doc_dstu2.html) for more information on supporting multiple versions of FHIR.
## Introducing the FHIR Context
HAPI defines model classes for every resource type and datatype defined by the FHIR specification. For example, here is the [Patient](../apidocs/hapi-fhir-structures-r4/ca/uhn/fhir/model/r4/resource/Patient.html) resource specification. If you browse the JavaDoc you will see getters and setters for the various properties that make up a Patient resource.
HAPI defines model classes for every resource type and datatype defined by the FHIR specification. For example, here is the [Patient](/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/Patient.html) resource specification. If you browse the JavaDoc you will see getters and setters for the various properties that make up a Patient resource.
We will come back to how to interact with these objects in a moment, but first we need to create a [FhirContext](../apidocs/hapi-fhir-base/ca/uhn/fhir/context/FhirContext.html). FhirContext is the starting point to using HAPI, and acts as a factory for most other parts of the API as well as a runtime cache of information that HAPI needs to operate. Users of the JAXB API may find this class to be similar in purpose to the [JAXBContext](http://docs.oracle.com/javaee/5/api/javax/xml/bind/JAXBContext.html) class from that API.
We will come back to how to interact with these objects in a moment, but first we need to create a [FhirContext](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/context/FhirContext.html). FhirContext is the starting point to using HAPI, and acts as a factory for most other parts of the API as well as a runtime cache of information that HAPI needs to operate. Users of the JAXB API may find this class to be similar in purpose to the [JAXBContext](http://docs.oracle.com/javaee/5/api/javax/xml/bind/JAXBContext.html) class from that API.
Creating a FhirContext is as simple as instantiating one. A FhirContext instance is specific to a given version of the FHIR specification, so it is recommended that you use one of the factory methods indicating the FHIR version you wish to support in your application, as shown in the following snippet:
@ -31,7 +29,7 @@ Creating a FhirContext is as simple as instantiating one. A FhirContext instance
## Parsing a resource from a String
This [Parser instance](../apidocs/hapi-fhir-base/ca/uhn/fhir/parser/IParser.html) can then be used to parse messages. Note that you may use the context to create as many parsers are you want.
This [Parser instance](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/parser/IParser.html) can then be used to parse messages. Note that you may use the context to create as many parsers are you want.
**Performance tip:** The FhirContext is an expensive object to create, so you should try to create it once and keep it around during the life of your application. Parsers, on the other hand, are very lightweight and do not need to be reused.

View File

@ -12,7 +12,7 @@ The following table shows the modules that make up the HAPI FHIR library.
<tr>
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-base</td>
<td>
<a href="../../apidocs/hapi-fhir-base/">JavaDoc</a>
<a href="/hapi-fhir/apidocs/hapi-fhir-base/">JavaDoc</a>
</td>
<td>
This is the core HAPI FHIR library and is always required in order to use
@ -35,7 +35,7 @@ The following table shows the modules that make up the HAPI FHIR library.
<tr>
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-dstu2</td>
<td>
<a href="../../apidocs/hapi-fhir-structures-dstu2/">JavaDoc</a>
<a href="/hapi-fhir/apidocs/hapi-fhir-structures-dstu2/">JavaDoc</a>
</td>
<td>
This module contains FHIR DSTU2 model classes.
@ -44,7 +44,7 @@ The following table shows the modules that make up the HAPI FHIR library.
<tr>
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-hl7org-dstu2</td>
<td>
<a href="../../apidocs/hapi-fhir-structures-hl7org-dstu2/">JavaDoc</a>
<a href="/hapi-fhir/apidocs/hapi-fhir-structures-hl7org-dstu2/">JavaDoc</a>
</td>
<td>
This module contains alternate FHIR DSTU2 model classes. The HAPI FHIR and FHIR "Java Reference
@ -58,7 +58,7 @@ The following table shows the modules that make up the HAPI FHIR library.
<tr>
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-dstu3</td>
<td>
<a href="../../apidocs/hapi-fhir-structures-dstu3/">JavaDoc</a>
<a href="/hapi-fhir/apidocs/hapi-fhir-structures-dstu3/">JavaDoc</a>
</td>
<td>
This module contains FHIR DSTU3 model classes.
@ -67,7 +67,7 @@ The following table shows the modules that make up the HAPI FHIR library.
<tr>
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-r4</td>
<td>
<a href="../../apidocs/hapi-fhir-structures-r4/">JavaDoc</a>
<a href="/hapi-fhir/apidocs/hapi-fhir-structures-r4/">JavaDoc</a>
</td>
<td>
This module contains FHIR R4 model classes.
@ -76,7 +76,7 @@ The following table shows the modules that make up the HAPI FHIR library.
<tr>
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-r5</td>
<td>
<a href="../../apidocs/hapi-fhir-structures-r5/">JavaDoc</a>
<a href="/hapi-fhir/apidocs/hapi-fhir-structures-r5/">JavaDoc</a>
</td>
<td>
This module contains FHIR R5 model classes.
@ -85,7 +85,7 @@ The following table shows the modules that make up the HAPI FHIR library.
<tr>
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-converter</td>
<td>
<a href="../../apidocs/hapi-fhir-converter/">JavaDoc</a>
<a href="/hapi-fhir/apidocs/hapi-fhir-converter/">JavaDoc</a>
</td>
<td>
This module contains converters for converting between FHIR versions.
@ -99,7 +99,7 @@ The following table shows the modules that make up the HAPI FHIR library.
<tr>
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-client</td>
<td>
<a href="../../apidocs/hapi-fhir-client/">JavaDoc</a>
<a href="/hapi-fhir/apidocs/hapi-fhir-client/">JavaDoc</a>
</td>
<td>
This module contains the core FHIR client framework, including an
@ -192,7 +192,7 @@ The following table shows the modules that make up the HAPI FHIR library.
<tr>
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-server</td>
<td>
<a href="../../apidocs/hapi-fhir-server/">JavaDoc</a>
<a href="/hapi-fhir/apidocs/hapi-fhir-server/">JavaDoc</a>
</td>
<td>
This module contains the HAPI FHIR Server framework, which can be used to
@ -202,7 +202,7 @@ The following table shows the modules that make up the HAPI FHIR library.
<tr>
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-jpaserver-base</td>
<td>
<a href="../../apidocs/hapi-fhir-jpaserver-base/">JavaDoc</a>
<a href="/hapi-fhir/apidocs/hapi-fhir-jpaserver-base/">JavaDoc</a>
</td>
<td>
This module contains the HAPI FHIR "JPA Server", which is a complete

View File

@ -1,11 +1,17 @@
# FHIR and HAPI FHIR Versions
<!--/*
NOTE: This is a one-section page. Don't add more sections, since it will then
add a TOC and make it harder to read. Horizontal real estate is precious on
this page.
*/-->
The following table shows the various versions of the HAPI FHIR library, and the versions of the FHIR standard that they support. Note that support for stable releases of FHIR are shown in <span style="background: #CEC; padding: 3px;">GREEN</span> and support for draft pre-release versions of FHIR are shown in <span style="background: #EEB; padding: 3px;">YELLOW</span>.
Note also that after the release of the FHIR DSTU2 specification, the FHIR
standard itself stopped using the DSTUx naming scheme, in favour or naming new releases STUx or simply Rx. Because HAPI FHIR already had draft support for what was then called DSTU3 at this time, we did not update our naming conventions until R4 in order to avoid breaking existing users' code. From the perspective of a user of HAPI FHIR, consider the terms DSTU3 / STU3 / R3 to be interchangeable.
<table class="table table-condensed">
<table class="table table-condensed versions-table">
<thead>
<tr>
<td><b>HAPI Version</b></td>
@ -22,232 +28,232 @@ Note also that after the release of the FHIR DSTU2 specification, the FHIR
<tr>
<td>HAPI FHIR 1.1</td>
<td>JDK6</td>
<td style="background: #CEC;">0.0.82</td>
<td style="background: #EEB;">0.5.0<span class="download-version-hash">-5843</span></td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-draft">0.0.82</td>
<td class="versions-table-cell-release">0.5.0<span class="download-version-hash">-5843</span></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 1.2</td>
<td>JDK6</td>
<td style="background: #CEC;">0.0.82</td>
<td style="background: #EEB;">0.5.0<span class="download-version-hash">-5843</span></td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-draft">0.0.82</td>
<td class="versions-table-cell-release">0.5.0<span class="download-version-hash">-5843</span></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 1.3</td>
<td>JDK6</td>
<td style="background: #CEC;">0.0.82</td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-draft">0.0.82</td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 1.4</td>
<td>JDK6</td>
<td style="background: #CEC;">0.0.82</td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #DDD;"></td>
<td style="background: #EEB;">1.3.0<span class="download-version-hash">-7602</span></td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-draft">0.0.82</td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-release">1.3.0<span class="download-version-hash">-7602</span></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 1.5</td>
<td>JDK6</td>
<td style="background: #CEC;">0.0.82</td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #DDD;"></td>
<td style="background: #EEB;">1.4.0<span class="download-version-hash">-8138</span></td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-draft">0.0.82</td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-release">1.4.0<span class="download-version-hash">-8138</span></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 1.6</td>
<td>JDK6</td>
<td style="background: #CEC;">0.0.82</td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #DDD;"></td>
<td style="background: #EEB;">1.4.0<span class="download-version-hash">-8636</span></td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-draft">0.0.82</td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-release">1.4.0<span class="download-version-hash">-8636</span></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 2.0</td>
<td>JDK6</td>
<td style="background: #CEC;">0.0.82</td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #DDD;"></td>
<td style="background: #EEB;">1.6.0<span class="download-version-hash">-9663</span></td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-draft">0.0.82</td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-release">1.6.0<span class="download-version-hash">-9663</span></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 2.1</td>
<td>JDK6</td>
<td style="background: #CEC;">0.0.82</td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #DDD;"></td>
<td style="background: #EEB;">1.7.0<span class="download-version-hash">-10129</span></td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-draft">0.0.82</td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-release">1.7.0<span class="download-version-hash">-10129</span></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 2.2</td>
<td>JDK6</td>
<td style="background: #CEC;">0.0.82</td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #EEB;">1.4.0</td>
<td style="background: #EEB;">1.8.0<span class="download-version-hash">-10528</span></td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-draft">0.0.82</td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-release">1.4.0</td>
<td class="versions-table-cell-release">1.8.0<span class="download-version-hash">-10528</span></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 2.3</td>
<td>JDK6</td>
<td style="background: #CEC;">0.0.82</td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #EEB;">1.4.0</td>
<td style="background: #EEB;">1.9.0<span class="download-version-hash">-11501</span></td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-draft">0.0.82</td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-release">1.4.0</td>
<td class="versions-table-cell-release">1.9.0<span class="download-version-hash">-11501</span></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 2.4</td>
<td>JDK6</td>
<td style="background: #CEC;">0.0.82</td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #EEB;">1.4.0</td>
<td style="background: #CEC;">3.0.1</td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-draft">0.0.82</td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-release">1.4.0</td>
<td class="versions-table-cell-draft">3.0.1</td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 2.5</td>
<td>JDK6</td>
<td style="background: #CEC;">0.0.82</td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #EEB;">1.4.0</td>
<td style="background: #CEC;">3.0.1</td>
<td style="background: #DDD;"></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-draft">0.0.82</td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-release">1.4.0</td>
<td class="versions-table-cell-draft">3.0.1</td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 3.0.0</td>
<td>JDK7</td>
<td style="background: #DDD;"></td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #EEB;">1.4.0</td>
<td style="background: #CEC;">3.0.1</td>
<td style="background: #EEB;">3.1.0<span class="download-version-hash">-12370</span></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-release">1.4.0</td>
<td class="versions-table-cell-draft">3.0.1</td>
<td class="versions-table-cell-release">3.1.0<span class="download-version-hash">-12370</span></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 3.1.0</td>
<td>JDK7</td>
<td style="background: #DDD;"></td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #EEB;">1.4.0</td>
<td style="background: #CEC;">3.0.1</td>
<td style="background: #EEB;">3.1.0<span class="download-version-hash">-12370</span></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-release">1.4.0</td>
<td class="versions-table-cell-draft">3.0.1</td>
<td class="versions-table-cell-release">3.1.0<span class="download-version-hash">-12370</span></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 3.2.0</td>
<td>JDK7</td>
<td style="background: #DDD;"></td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #EEB;">1.4.0</td>
<td style="background: #CEC;">3.0.1</td>
<td style="background: #EEB;">3.2.0<span class="download-version-hash">-12917</span></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-release">1.4.0</td>
<td class="versions-table-cell-draft">3.0.1</td>
<td class="versions-table-cell-release">3.2.0<span class="download-version-hash">-12917</span></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 3.3.0</td>
<td>JDK7</td>
<td style="background: #DDD;"></td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #EEB;">1.4.0</td>
<td style="background: #CEC;">3.0.1</td>
<td style="background: #EEB;">3.2.0<span class="download-version-hash">-13271</span></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-release">1.4.0</td>
<td class="versions-table-cell-draft">3.0.1</td>
<td class="versions-table-cell-release">3.2.0<span class="download-version-hash">-13271</span></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 3.4.0</td>
<td>JDK8</td>
<td style="background: #DDD;"></td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #EEB;">1.4.0</td>
<td style="background: #CEC;">3.0.1</td>
<td style="background: #EEB;">3.4.0<span class="download-version-hash">-13732</span></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-release">1.4.0</td>
<td class="versions-table-cell-draft">3.0.1</td>
<td class="versions-table-cell-release">3.4.0<span class="download-version-hash">-13732</span></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 3.5.0</td>
<td>JDK8</td>
<td style="background: #DDD;"></td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #EEB;">1.4.0</td>
<td style="background: #CEC;">3.0.1</td>
<td style="background: #EEB;">3.4.0<span class="download-version-hash">-13732</span></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-release">1.4.0</td>
<td class="versions-table-cell-draft">3.0.1</td>
<td class="versions-table-cell-release">3.4.0<span class="download-version-hash">-13732</span></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 3.6.0</td>
<td>JDK8</td>
<td style="background: #DDD;"></td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #EEB;">1.4.0</td>
<td style="background: #CEC;">3.0.1</td>
<td style="background: #EEB;">3.6.0<span class="download-version-hash">-1202b2eed0f</span></td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-release">1.4.0</td>
<td class="versions-table-cell-draft">3.0.1</td>
<td class="versions-table-cell-release">3.6.0<span class="download-version-hash">-1202b2eed0f</span></td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 3.7.0</td>
<td>JDK8</td>
<td style="background: #DDD;"></td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #EEB;">1.4.0</td>
<td style="background: #CEC;">3.0.1</td>
<td style="background: #CEC;">4.0.0</td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-release">1.4.0</td>
<td class="versions-table-cell-draft">3.0.1</td>
<td class="versions-table-cell-draft">4.0.0</td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 3.8.0</td>
<td>JDK8</td>
<td style="background: #DDD;"></td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #EEB;">1.4.0</td>
<td style="background: #CEC;">3.0.1</td>
<td style="background: #CEC;">4.0.0</td>
<td style="background: #DDD;"></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-release">1.4.0</td>
<td class="versions-table-cell-draft">3.0.1</td>
<td class="versions-table-cell-draft">4.0.0</td>
<td class="versions-table-cell-empty"></td>
</tr>
<tr>
<td>HAPI FHIR 4.0.0</td>
<td>JDK8</td>
<td style="background: #DDD;"></td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #EEB;">1.4.0</td>
<td style="background: #CEC;">3.0.1</td>
<td style="background: #CEC;">4.0.0</td>
<td style="background: #EEB;">4.1.0<span class="download-version-hash">-e0e3caf9ba</span></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-release">1.4.0</td>
<td class="versions-table-cell-draft">3.0.1</td>
<td class="versions-table-cell-draft">4.0.0</td>
<td class="versions-table-cell-release">4.1.0<span class="download-version-hash">-e0e3caf9ba</span></td>
</tr>
<tr>
<td>HAPI FHIR 4.1.0</td>
<td>JDK8</td>
<td style="background: #DDD;"></td>
<td style="background: #CEC;">1.0.2</td>
<td style="background: #EEB;">1.4.0</td>
<td style="background: #CEC;">3.0.2</td>
<td style="background: #CEC;">4.0.1</td>
<td style="background: #EEB;">4.1.0<span class="download-version-hash">-1a7623d866</span></td>
<td class="versions-table-cell-empty"></td>
<td class="versions-table-cell-draft">1.0.2</td>
<td class="versions-table-cell-release">1.4.0</td>
<td class="versions-table-cell-draft">3.0.2</td>
<td class="versions-table-cell-draft">4.0.1</td>
<td class="versions-table-cell-release">4.1.0<span class="download-version-hash">-1a7623d866</span></td>
</tr>
</tbody>
</table>

View File

@ -5,7 +5,7 @@ This page describes how to extend and constrain the FHIR data model for your own
# Extensions
<p class="doc_info_bubble">
Note on FHIR Versions: Because of the differences in the way the structures work between DSTU2 and DSTU3, we have provided two versions of many of the examples on this page. See the <a href="/hapi-fhir/download.html">download page</a> for more information on FHIR versions.
Note on FHIR Versions: Because of the differences in the way the structures work between DSTU2 and DSTU3, we have provided two versions of many of the examples on this page. See the <a href="/hapi-fhir/docs/introduction/versions.html">FHIR Versions</a> page for more information on FHIR version support in HAPI FHIR.
</p>
Extensions are a key part of the FHIR specification, providing a standardized way of placing additional data in a resource.

View File

@ -0,0 +1,168 @@
# Resource References
Resource references are a key part of the HAPI FHIR model, since almost any resource will have references to other resources within it.
The [Reference](/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/Reference.html) type is the datatype for references. This datatype has a number of properties which help make working with FHIR simple.
The `getReference()` method returns a String that contains the identity of the resource being referenced. This is the item which is most commonly populated when interacting with FHIR. For example, consider the following Patient resource, which contains a reference to an Organization resource:
```json
{
"resourceType": "Patient",
"identifier": [{
"system": "http://example.com/identifiers",
"value": "12345"
}],
"managingOrganization": {
"reference": "Organization/123"
}
}
```
Given a Patient resource obtained by invoking a client operation, a call to `String reference = patient.getManagingOrganization().getReference();` returns a String containing `Organization/112`.
Reference also has a place for storing actual resource instances (i.e. an actual [IBaseResource](/hapi-fhir/apidocs/hapi-fhir-base/org/hl7/fhir/instance/model/api/IBaseResource.html) instance), and this can be very useful as shown below.
# References in Client Code
In client code, if a resource reference refers to a resource which was received as a part of the same response, <code>getResource()</code> will be populated with the actual resource. This can happen because either the resource was received as a contained resource, or the resource was received as a separate resource in a bundle.
# References in Server Code
In server code, you will often want to return a resource which contains a link to another resource. Generally these "linked" resources are not actually included in the response, but rather a link to the resource is included and the client may request that resource directly (by ID) if it is needed.
The following example shows a Patient resource being created which will have a link to its managing organization when encoded from a server:
```java
Patient patient = new Patient();
patient.setId("Patient/1333");
patient.addIdentifier("urn:mrns", "253345");
patient.getManagingOrganization().setReference("Organization/124362");
```
## Handling Includes (_include) in a Bundle
Your server code may also wish to add additional resource to a bundle being returned (e.g. because of an _include directive in the client's request).
To do this, you can implement your server method to simply return List<IBaseResource> and then simply add your extra resources to the list. Another technique however, is to populate the reference as shown in the example below, but ensure that the referenced resource has an ID set.
In the following example, the Organization resource has an ID set, so it will not be contained but will rather appear as a distinct entry in any returned bundles. Both resources are added to a bundle, which will then have two entries:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/IncludesExamples.java|addIncludes}}
```
This will give the following output:
```xml
<Bundle xmlns="http://hl7.org/fhir">
<id value="4e151274-2b19-4930-97f2-8427167a176c"/>
<type value="searchset"/>
<total value="1"/>
<link>
<relation value="fhir-base"/>
<url value="http://example.com/base"/>
</link>
<link>
<relation value="self"/>
<url value="http://example.com/base/Patient"/>
</link>
<entry>
<resource>
<Patient xmlns="http://hl7.org/fhir">
<id value="1333"/>
<identifier>
<system value="urn:mrns"/>
<value value="253345"/>
</identifier>
<managingOrganization>
<reference value="Organization/65546"/>
</managingOrganization>
</Patient>
</resource>
</entry>
<entry>
<resource>
<Organization xmlns="http://hl7.org/fhir">
<id value="65546"/>
<name value="Test Organization"/>
</Organization>
</resource>
<search>
<mode value="include"/>
</search>
</entry>
</Bundle>
````
## Contained Resources
On the other hand, if the linked resource does not have an ID set, the linked resource will be included in the returned bundle as a "contained" resource. In this case, HAPI itself will define a local reference ID (e.g. `#1`).
```java
// Create an organization, note that the organization does not have an ID
Organization org = new Organization();
org.getName().setValue("Contained Test Organization");
// Create a patient
Patient patient = new Patient();
patient.setId("Patient/1333");
patient.addIdentifier("urn:mrns", "253345");
// Put the organization as a reference in the patient resource
patient.getManagingOrganization().setResource(org);
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
System.out.println(encoded);
```
This will give the following output:
```xml
<Patient xmlns="http://hl7.org/fhir">
<contained>
<Organization xmlns="http://hl7.org/fhir" id="1">
<name value="Contained Test Organization"/>
</Organization>
</contained>
<identifier>
<system value="urn:mrns"/>
<value value="253345"/>
</identifier>
<managingOrganization>
<reference value="#1"/>
</managingOrganization>
</Patient>
```
Note that you may also "contain" resources manually in your own code if you prefer. The following example show how to do this:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ResourceRefs.java|manualContained}}
```
# Versioned References
By default, HAPI will strip resource versions from references between resources. For example, if you set a reference to `Patient.managingOrganization` to the value `Patient/123/_history/2`, HAPI will encode this reference as `Patient/123`.
This is because in most circumstances, references between resources should be versionless (e.g. the reference just points to the latest version, whatever version that might be).
There are valid circumstances however for wanting versioned references. If you need HAPI to emit versionned references, you have a few options:
You can force the parser to never strip versions:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/Parser.java|disableStripVersions}}
```
You can also disable this behaviour entirely on the context (so that it will apply to all parsers):
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/Parser.java|disableStripVersionsCtx}}
```
You can also configure HAPI to not strip versions only on certain fields. This is desirable if you want versionless references in most places but need them in some places:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/Parser.java|disableStripVersionsField}}
```

View File

@ -1,6 +1,6 @@
# Authorization Interceptor
HAPI FHIR 1.5 introduced a new interceptor: [AuthorizationInterceptor](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptor.html).
HAPI FHIR 1.5 introduced a new interceptor: [AuthorizationInterceptor](/hapi-fhir/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptor.html).
This interceptor can help with the complicated task of determining whether a user has the appropriate permission to perform a given task on a FHIR server. This is done by declaring a set of rules that can selectively allow (whitelist) and/or selectively block (blacklist) requests.
@ -28,7 +28,7 @@ Note that there are performance implications to this mechanism, since an unautho
See the following diagram for an example of how this works.
<img src="/docs/images/hapi_authorizationinterceptor_read_normal.svg" alt="Write Authorization"/>
<img src="/hapi-fhir/docs/images/hapi_authorizationinterceptor_read_normal.svg" alt="Write Authorization"/>
## Authorizing Write Operations
@ -36,7 +36,7 @@ Write operations (create, update, etc.) are typically authorized by the intercep
See the following diagram for an example of how this works.
<img src="/docs/images/hapi_authorizationinterceptor_write_normal.svg" alt="Write Authorization"/>
<img src="/hapi-fhir/docs/images/hapi_authorizationinterceptor_write_normal.svg" alt="Write Authorization"/>
<a name="authorizing-sub-operations"/>

View File

@ -1,6 +1,6 @@
# Consent Interceptor
HAPI FHIR 4.0.0 introduced a new interceptor, the [ConsentInterceptor](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/consent/ConsentInterceptor.html).
HAPI FHIR 4.0.0 introduced a new interceptor, the [ConsentInterceptor](/hapi-fhir/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/consent/ConsentInterceptor.html).
The consent interceptor may be used to examine client requests to apply consent directives and create audit trail events. Like the AuthorizationInterceptor above, this interceptor is not a complete working solution, but instead is a framework designed to make it easier to implement local policies.
@ -16,7 +16,7 @@ The consent interceptor has several primary purposes:
* The consent service suppresses search the total being returned in Bundle.total for search results.
The ConsentInterceptor requires a user-supplied instance of the [IConsentService](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/consent/IConsentService.html) interface. The following shows a simple example of an IConsentService implementation:
The ConsentInterceptor requires a user-supplied instance of the [IConsentService](/hapi-fhir/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/consent/IConsentService.html) interface. The following shows a simple example of an IConsentService implementation:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ConsentInterceptors.java|service}}

View File

@ -1,6 +1,6 @@
# Search Narrowing Interceptor
HAPI FHIR 3.7.0 introduced a new interceptor, the [SearchNarrowingInterceptor](/apidocs/hapi-fhr-server/ca/uhn/fhir/rest/server/interceptor/auth/SearchNarrowingInterceptor.html).
HAPI FHIR 3.7.0 introduced a new interceptor, the [SearchNarrowingInterceptor](/hapi-fhir/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/auth/SearchNarrowingInterceptor.html).
This interceptor is designed to be used in conjunction with AuthorizationInterceptor. It uses a similar strategy where a dynamic list is built up for each request, but the purpose of this interceptor is to modify client searches that are received (after HAPI FHIR received the HTTP request, but before the search is actually performed) to restrict the search to only search for specific resources or compartments that the user has access to.

View File

@ -4,7 +4,7 @@
The HAPI JPA Server has the following components:
* **Resource Providers:** A RESTful server [Resource Provider](/hapi-fhir/docs/server/restful_server.html#resource_providers) is provided for each resource type in a given release of FHIR. Each resource provider implements a [@Search](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Search.html) method implementing the complete set of search parameters defined in the FHIR specification for the given resource type.
* **Resource Providers:** A RESTful server [Resource Provider](/hapi-fhir/docs/server_plain/resource_providers.html) is provided for each resource type in a given release of FHIR. Each resource provider implements a [@Search](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Search.html) method implementing the complete set of search parameters defined in the FHIR specification for the given resource type.
The resource providers also extend a superclass which implements all of the other FHIR methods, such as Read, Create, Delete, etc.

View File

@ -1,6 +1,6 @@
# JPA Server Introduction
The HAPI FHIR [RestfulServer](/hapi-fhir/docs/server/restful_server.html) module can be used to create a FHIR server endpoint against an arbitrary data source, which could be a database of your own design, an existing clinical system, a set of files, or anything else you come up with.
The HAPI FHIR [Plain Server](/hapi-fhir/docs/server_plain/introduction.html) module can be used to create a FHIR server endpoint against an arbitrary data source, which could be a database of your own design, an existing clinical system, a set of files, or anything else you come up with.
HAPI also provides a persistence module which can be used to provide a complete RESTful server implementation, backed by a database of your choosing. This module uses the [JPA 2.0](http://en.wikipedia.org/wiki/Java_Persistence_API) API to store data in a database without depending on any specific database technology.
@ -69,7 +69,7 @@ web address.
A common use for logical references is in references to conformance resources, such as ValueSets, StructureDefinitions, etc. For example, you might refer to the ValueSet `http://hl7.org/fhir/ValueSet/quantity-comparator` from your own resources. In this case, you are not necessarily telling the server that this is a real address that it should resolve, but rather that this is an identifier for a ValueSet where `ValueSet.url` has the given URI/URL.
HAPI can be configured to treat certain URI/URL patterns as logical by using the DaoConfig#setTreatReferencesAsLogical property (see [JavaDoc](/hapi-fhir/apidocs/hapi-fhir-jpaserver-base/ca/uhn/fhir/jpa/dao/DaoConfig.html#setTreatReferencesAsLogical-java.util.Set-)).
HAPI can be configured to treat certain URI/URL patterns as logical by using the DaoConfig#setTreatReferencesAsLogical property (see [JavaDoc](/hapi-fhir/apidocs/hapi-fhir-jpaserver-base/ca/uhn/fhir/jpa/dao/DaoConfig.html#setTreatReferencesAsLogical(java.util.Set))).
For example:

View File

@ -56,7 +56,7 @@ This strategy is shown in the following example:
## Other Strategies
See the [IServerAddressStrategy](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/IServerAddressStrategy.html) JavaDoc (specifically the list of "All Known Implementing Classes") to see other strategies that are available.
See the [IServerAddressStrategy](/hapi-fhir/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/IServerAddressStrategy.html) JavaDoc (specifically the list of "All Known Implementing Classes") to see other strategies that are available.
<a name="capabilities"/>
@ -64,7 +64,7 @@ See the [IServerAddressStrategy](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/serv
The HAPI FHIR RESTful Server will automatically generate a Server [CapabilityStatement](http://hl7.org/fhir/capabilitystatement.html) resource (or a Server [Conformance](https://www.hl7.org/fhir/DSTU2/conformance.html) resource for FHIR DSTU2).
This statement is automatically generated based on the various annotated methods which are provided to the server. This behaviour may be modified by creating a new class containing a method annotated with a [@Metadata annotation](./restful_operations.html#system_conformance) and then passing an instance of that class to the [setServerConformanceProvider(Object)](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/RestfulServer.html#setServerConformanceProvider(java.lang.Object)) method on your RestfulServer instance.
This statement is automatically generated based on the various annotated methods which are provided to the server. This behaviour may be modified by creating a new class containing a method annotated with a [@Metadata annotation](./rest_operations.html#system_capabilities) and then passing an instance of that class to the [setServerConformanceProvider(Object)](/hapi-fhir/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/RestfulServer.html#setServerConformanceProvider(java.lang.Object)) method on your RestfulServer instance.
## Enhancing the Generated CapabilityStatement
@ -72,12 +72,12 @@ If you have a need to add your own content (special extensions, etc.) to your se
The generator class is version-specific, so you will need to extend the class appropriate for the version of FHIR you are implementing:
* DSTU3: [ca.uhn.fhir.rest.server.provider.dstu2.ServerConformanceProvider](/apidocs/hapi-fhir-structures-dstu2/ca/uhn/fhir/rest/server/provider/dstu2.ServerConformanceProvider.html)
* DSTU3: [org.hl7.fhir.dstu3.hapi.rest.server.ServerCapabilityStatementProvider](/apidocs/hapi-fhir-structures-dstu3/org/hl7/fhir/dstu3/hapi/rest/server/ServerCapabilityStatementProvider.html)
* R4: [org.hl7.fhir.r4.hapi.rest.server.ServerCapabilityStatementProvider](/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/hapi/rest/server/ServerCapabilityStatementProvider.html)
* R5: [org.hl7.fhir.r5.hapi.rest.server.ServerCapabilityStatementProvider](/apidocs/hapi-fhir-structures-r5/org/hl7/fhir/r5/hapi/rest/server/ServerCapabilityStatementProvider.html)
* DSTU3: [ca.uhn.fhir.rest.server.provider.dstu2.ServerConformanceProvider](/hapi-fhir/apidocs/hapi-fhir-structures-dstu2/ca/uhn/fhir/rest/server/provider/dstu2/ServerConformanceProvider.html)
* DSTU3: [org.hl7.fhir.dstu3.hapi.rest.server.ServerCapabilityStatementProvider](/hapi-fhir/apidocs/hapi-fhir-structures-dstu3/org/hl7/fhir/dstu3/hapi/rest/server/ServerCapabilityStatementProvider.html)
* R4: [org.hl7.fhir.r4.hapi.rest.server.ServerCapabilityStatementProvider](/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/hapi/rest/server/ServerCapabilityStatementProvider.html)
* R5: [org.hl7.fhir.r5.hapi.rest.server.ServerCapabilityStatementProvider](/hapi-fhir/apidocs/hapi-fhir-structures-r5/org/hl7/fhir/r5/hapi/rest/server/ServerCapabilityStatementProvider.html)
In your own class extending this class, you can override the [`getServerConformance()`](/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/hapi/rest/server/ServerCapabilityStatementProvider.html#getServerConformance()) method to provide your own implementation. In this method, call `super.getServerConformance()` to obtain the built-in conformance statement and then add your own information to it.
In your own class extending this class, you can override the [`getServerConformance()`](/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/hapi/rest/server/ServerCapabilityStatementProvider.html#getServerConformance(javax.servlet.http.HttpServletRequest,ca.uhn.fhir.rest.api.server.RequestDetails)) method to provide your own implementation. In this method, call `super.getServerConformance()` to obtain the built-in conformance statement and then add your own information to it.
# Controlling Response Contents / Encoding / Formatting

View File

@ -0,0 +1,57 @@
# JAX-RS Server
The HAPI FHIR Plain Server ([RestfulServer](/hapi-fhir/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/RestfulServer.html)) 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](https://jax-rs-spec.java.net/nonav/2.0/apidocs/index.html).
<div class="doc_info_bubble">
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!
</div>
## Features
The server currently supports:
* Automatic [Capability Statement Generation](./introduction.html#capabilities)
* [@Read](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Read.html)
* [@RSearch](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Search.html)
* [@Create](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Create.html)
* [@Update](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Update.html)
* [@Delete](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Delete.html)
* [@Operation](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Operation.html)
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](https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jaxrsserver-example).
# 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](./rest_operations.html) on the methods in the [Resource Providers](./resource_providers.html) in order to be able to call them.
Implementing a JAX-RS Resource Provider requires some JAX-RS annotations. The [@Path](https://docs.oracle.com/javaee/6/api/javax/ws/rs/Path.html) annotation needs to define the resource path. The <code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/Produces.html">@Produces</a></code> 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](/hapi-fhir/apidocs/hapi-fhir-jaxrsserver-base/ca/uhn/fhir/jaxrs/server/AbstractJaxRsResourceProvider.html).
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/JaxRsPatientRestProvider.java|jax-rs-provider-construction}}
```
## Extended Operations
[Extended Operations](./rest_operations_operations.html) require the correct JAX-RS (
[@Path](https://docs.oracle.com/javaee/6/api/javax/ws/rs/Path.html), [@GET](https://docs.oracle.com/javaee/6/api/javax/ws/rs/GET.html) or [@POST](https://docs.oracle.com/javaee/6/api/javax/ws/rs/POST.html) 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.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/JaxRsPatientRestProvider.java|jax-rs-provider-operation}}
```
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](/hapi-fhir/apidocs/hapi-fhir-jaxrsserver-base/ca/uhn/fhir/jaxrs/server/AbstractJaxRsConformanceProvider.html#getProviders()). This method is called once, during [PostConstruct](https://docs.oracle.com/javaee/6/api/javax/annotation/PostConstruct.html).
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/JaxRsConformanceProvider.java|jax-rs-conformance}}
```
# A Complete Example
A complete example showing how to implement a JAX-RS RESTful server can be found in our Git repo here:
* [hapi-fhir-jaxrsserver-example](https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jaxrsserver-example)

View File

@ -8,7 +8,7 @@ This means that additional logic will be performed during request parsing to det
Using URL Base Multitenancy means that an additional element is added to the path of each resource between the server base URL and the resource name. For example, if your restful server is deployed to `http://acme.org:8080/baseDstu3` and a client wishes to access Patient 123 for Tenant "FOO", the resource ID (and URL to fetch that resource) would be `http://acme.org:8080/FOO/Patient/123`.
To enable this mode on your server, simply provide the [UrlBaseTenantIdentificationStrategy](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/tenant/UrlBaseTenantIdentificationStrategy.html) to the server as shown below:
To enable this mode on your server, simply provide the [UrlBaseTenantIdentificationStrategy](/hapi-fhir/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/tenant/UrlBaseTenantIdentificationStrategy.html) to the server as shown below:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/Multitenancy.java|enableUrlBaseTenantIdentificationStrategy}}

View File

@ -8,7 +8,7 @@ There are two complementary parts to the HAPI FHIR server paging support: paging
## Paging Providers
To support paging, a server must have an [IPagingProvider](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/IPagingProvider.html) implementation set. The paging provider is used to store resource return lists between incoming calls by clients.
To support paging, a server must have an [IPagingProvider](/hapi-fhir/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/IPagingProvider.html) implementation set. The paging provider is used to store resource return lists between incoming calls by clients.
A paging provider provides two key methods:
@ -26,7 +26,7 @@ The following example shows a server implementation with paging support.
# Bundle Providers
If a server supports a paging provider, a further optimization is to also use a bundle provider. A bundle provider simply takes the place of the `List<IBaseResource>` return type in your provider methods. In other words, instead of returning *List<IBaseResource>*, your search method will return [IBundleProvider](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/IBundleProvider.html).
If a server supports a paging provider, a further optimization is to also use a bundle provider. A bundle provider simply takes the place of the `List<IBaseResource>` return type in your provider methods. In other words, instead of returning *List<IBaseResource>*, your search method will return [IBundleProvider](/hapi-fhir/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/api/server/IBundleProvider.html).
When using a bundle provider however, the server will only request small sublists of resources as they are actually being returned. This allows servers to optimize by not loading all resources into memory until they are actually needed.
@ -46,5 +46,5 @@ Another option is to use "named pages", meaning that each page is simply assigne
In order to support named pages, the IPagingProvider must implement the `retrieveResultList(RequestDetails theRequestDetails, String theSearchId, String thePageId)` method.
Then, individual search/history methods may return a [BundleProviderWithNamedPages](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/BundleProviderWithNamedPages.html) or simply implement the `getPageId()` method on their own IBundleProvider implementation.
Then, individual search/history methods may return a [BundleProviderWithNamedPages](/hapi-fhir/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/BundleProviderWithNamedPages.html) or simply implement the `getPageId()` method on their own IBundleProvider implementation.

View File

@ -10,7 +10,7 @@ There are two types of providers that can be registered against a HAPI FHIR Plai
# Resource Providers
A Resource provider class must implement the [IResourceProvider](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/IResourceProvider.html) interface, and will contain one or more methods which have been annotated with special annotations indicating which RESTful operation that method supports. Below is a simple example of a resource provider which supports the FHIR [read](http://hl7.org/fhir/http.html#read) operation (i.e. retrieve a single resource by ID) as well as the FHIR [search](http://hl7.org/fhir/http.html#search) operation (i.e. find any resources matching a given criteria) for a specific search criteria.
A Resource provider class must implement the [IResourceProvider](/hapi-fhir/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/IResourceProvider.html) interface, and will contain one or more methods which have been annotated with special annotations indicating which RESTful operation that method supports. Below is a simple example of a resource provider which supports the FHIR [read](http://hl7.org/fhir/http.html#read) operation (i.e. retrieve a single resource by ID) as well as the FHIR [search](http://hl7.org/fhir/http.html#search) operation (i.e. find any resources matching a given criteria) for a specific search criteria.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProvider.java|provider}}
@ -18,7 +18,7 @@ A Resource provider class must implement the [IResourceProvider](/apidocs/hapi-f
## Adding more Methods (Search, History, Create, etc.)
You will probably wish to add more methods to your resource provider. See [RESTful Operations](./restful_operatons.html) for lots more examples of how to add methods for various operations.
You will probably wish to add more methods to your resource provider. See [REST Operations](./rest_operations.html) for lots more examples of how to add methods for various operations.
For now, we will move on to the next step though, which is creating the actual server to hold your resource providers and deploying that. Once you have this working, you might want to come back and start adding other operations.
@ -26,7 +26,7 @@ For now, we will move on to the next step though, which is creating the actual s
Once your resource providers are created, your next step is to define a server class.
HAPI provides a class called [RestfulServer](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/RestfulServer.html), which is a specialized Java Servlet. To create a server, you simply create a class which extends RestfulServer as shown in the example below.
HAPI provides a class called [RestfulServer](/hapi-fhir/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/RestfulServer.html), which is a specialized Java Servlet. To create a server, you simply create a class which extends RestfulServer as shown in the example below.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ExampleRestfulServlet.java|servlet}}
@ -42,15 +42,15 @@ In addition to **Resource Providers**, which are resource-type specific, a secon
Defining one provider per resource is a good strategy to keep code readable and maintainable, but it is also possible to put methods for multiple resource types in a provider class.
Providers which do not implement the [IResourceProvider](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/IResourceProvider.html) (and therefore are not bound to one specific resource type) are known as **Plain Providers**.
Providers which do not implement the [IResourceProvider](/hapi-fhir/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/IResourceProvider.html) (and therefore are not bound to one specific resource type) are known as **Plain Providers**.
A plain provider may implement any [RESTful operation](./restful_operations.html), but will generally need to explicitly state what type of resource it applies to. If the method directly returns a resource or a collection of resources (as in an [instance read](./restful_operations.htmnl.html#instance_read) or [type search](./restful_operations.html#type_search) operation) the resource type will be inferred automatically. If the method returns a [Bundle Resource](http://hl7.org/fhir/bundle.html), it is necessary to explicitly specify the resource type in the method annotation. The following example shows this:
A plain provider may implement any [REST operation](./rest_operations.html), but will generally need to explicitly state what type of resource it applies to. If the method directly returns a resource or a collection of resources (as in an [instance read](./rest_operations.html#instance_read) or [type search](./rest_operations.html#type_search) operation) the resource type will be inferred automatically. If the method returns a [Bundle Resource](http://hl7.org/fhir/bundle.html), it is necessary to explicitly specify the resource type in the method annotation. The following example shows this:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ExampleProviders.java|plainProvider}}
```
In addition, some methods are not resource specific. For example, the [system history](./restful_operations.html#system-history) operation returns historical versions of *all resource types* on a server, so it needs to be defined in a plain provider.
In addition, some methods are not resource specific. For example, the [system history](./rest_operations.html#history) operation returns historical versions of *all resource types* on a server, so it needs to be defined in a plain provider.
Once you have defined your plain providers, they are passed to the server in a similar way to the resource providers.
@ -60,7 +60,7 @@ Once you have defined your plain providers, they are passed to the server in a s
# Common Method Parameters
Different RESTful methods will have different requirements in terms of the method parameters they require, as described in the [RESTful Operations](./restful_operations.html) page.
Different RESTful methods will have different requirements in terms of the method parameters they require, as described in the [REST Operations](./rest_operations.html) page.
In addition, there are several parameters you may add in order to meet specific needs of your application.
@ -90,11 +90,11 @@ In many cases, you will want to respond to client requests with a specific HTTP
Sometimes this is simply a requirement of your specific application (e.g. you want to provide application specific HTTP status codes for certain types of errors), and other times this may be a requirement of the FHIR or HTTP specifications to respond in a specific way to certain conditions.
To customize the error that is returned by HAPI's server methods, you should throw an exception which extends HAPI's [BaseServerResponseException](/apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/exceptions/BaseServerResponseException.html) class. Various exceptions which extend this class will generate a different HTTP status code.
To customize the error that is returned by HAPI's server methods, you should throw an exception which extends HAPI's [BaseServerResponseException](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/server/exceptions/BaseServerResponseException.html) class. Various exceptions which extend this class will generate a different HTTP status code.
For example, the [ResourceNotFoundException](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/server/exceptions/ResourceNotFoundException.html) causes HAPI to return an `HTTP 404 Resource Not Found`. A complete list of available exceptions is available in the [exceptions package summary](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/server/exceptions/package-summary.html).
For example, the [ResourceNotFoundException](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/server/exceptions/ResourceNotFoundException.html) causes HAPI to return an `HTTP 404 Resource Not Found`. A complete list of available exceptions is available in the [exceptions package summary](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/server/exceptions/package-summary.html).
If you wish to return an HTTP status code for which there is no pre-defined exception, you may throw the [UnclassifiedServerFailureException](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/server/exceptions/UnclassifiedServerFailureException.html), which allows you to return any status code you wish.
If you wish to return an HTTP status code for which there is no pre-defined exception, you may throw the [UnclassifiedServerFailureException](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/server/exceptions/UnclassifiedServerFailureException.html), which allows you to return any status code you wish.
## Returning an OperationOutcome for Errors
@ -106,7 +106,7 @@ By default, HAPI will automatically generate an OperationOutcome which contains
# Server Lifecycle Methods
Resource providers may optionally want to be notified when the server they are registered with is being destroyed, so that they can perform cleanup. In this case, a method annotated with the [@Destroy](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Destroy.html) annotation can be added (this method should be public, return `void`, and take no parameters).
Resource providers may optionally want to be notified when the server they are registered with is being destroyed, so that they can perform cleanup. In this case, a method annotated with the [@Destroy](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Destroy.html) annotation can be added (this method should be public, return `void`, and take no parameters).
This method will be invoked once by the RestfulServer when it is shutting down.

View File

@ -1,12 +1,12 @@
# REST Operations: Overview
This page shows the operations which can be implemented on HAPI [Plain Server](/docs/server_plain/introduction.html), as well as on the [Annotation Client](/docs/client/annotation.html). Most of the examples shown here show how to implement a server method, but to perform an equivalent call on an annotation client you simply put a method with the same signature in your client interface.
This page shows the operations which can be implemented on HAPI [Plain Server](/docs/server_plain/introduction.html), as well as on the [Annotation Client](/docs/client/annotation_client.html). Most of the examples shown here show how to implement a server method, but to perform an equivalent call on an annotation client you simply put a method with the same signature in your client interface.
<a name="instance_read" />
# Instance Level - Read
The [read](http://hl7.org/fhir/http.html#read) operation retrieves a resource by ID. It is annotated with the [@Read](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Read.html) annotation, and has at least a single parameter annotated with the [@IdParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) annotation.
The [read](http://hl7.org/fhir/http.html#read) operation retrieves a resource by ID. It is annotated with the [@Read](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Read.html) annotation, and has at least a single parameter annotated with the [@IdParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) annotation.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|read}}
@ -28,7 +28,7 @@ The following snippet shows how to define a client interface to handle a read me
# Instance Level - VRead
The **[vread](http://hl7.org/implement/standards/fhir/http.html#vread)** operation retrieves a specific version of a resource with a given ID. To support vread, simply add "version=true" to your [@Read](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Read.html) annotation. This means that the read method will support both "Read" and "VRead". The IdType instance passed into your method may or may not have the version populated depending on the client's request.
The **[vread](http://hl7.org/implement/standards/fhir/http.html#vread)** operation retrieves a specific version of a resource with a given ID. To support vread, simply add "version=true" to your [@Read](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Read.html) annotation. This means that the read method will support both "Read" and "VRead". The IdType instance passed into your method may or may not have the version populated depending on the client's request.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|vread}}
@ -46,11 +46,11 @@ http://fhir.example.com/Patient/111/_history/2
The **[update](http://hl7.org/implement/standards/fhir/http.html#update)** operation updates a specific resource instance (using its ID), and optionally accepts a version ID as well (which can be used to detect version conflicts).
Update methods must be annotated with the [@Update](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Update.html) annotation, and have a parameter annotated with the [@ResourceParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ResourceParam.html) annotation. This parameter contains the resource instance to be created. See the [@ResourceParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ResourceParam.html) for information on the types allowed for this parameter (resource types, String, byte[]).
Update methods must be annotated with the [@Update](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Update.html) annotation, and have a parameter annotated with the [@ResourceParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ResourceParam.html) annotation. This parameter contains the resource instance to be created. See the [@ResourceParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ResourceParam.html) for information on the types allowed for this parameter (resource types, String, byte[]).
In addition, the method may optionally have a parameter annotated with the [@IdParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) annotation, or they may obtain the ID of the resource being updated from the resource itself. Either way, this ID comes from the URL passed in.
In addition, the method may optionally have a parameter annotated with the [@IdParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) annotation, or they may obtain the ID of the resource being updated from the resource itself. Either way, this ID comes from the URL passed in.
Update methods must return an object of type [MethodOutcome](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/api/MethodOutcome.html). This object contains the identity of the created resource.
Update methods must return an object of type [MethodOutcome](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/api/MethodOutcome.html). This object contains the identity of the created resource.
The following snippet shows how to define an update method on a server:
@ -72,7 +72,7 @@ The following snippet shows how the corresponding client interface would look:
## Conditional Updates
If you wish to support conditional updates, you can add a parameter tagged with a [@ConditionalOperationParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ConditionalOperationParam.html) annotation. If the request URL contains search parameters instead of a resource ID, then this parameter will be populated.
If you wish to support conditional updates, you can add a parameter tagged with a [@ConditionalUrlParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ConditionalUrlParam.html) annotation. If the request URL contains search parameters instead of a resource ID, then this parameter will be populated.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|updateConditional}}
@ -88,7 +88,7 @@ http://fhir.example.com/Patient?identifier=system%7C00001
## Accessing The Raw Resource Payload
If you wish to have access to the raw resource payload as well as the parsed value for any reason, you may also add parameters which have been annotated with the [@ResourceParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ResourceParam.html) of type `String` (to access the raw resource body) and/or `EncodingEnum` (to determine which encoding was used).
If you wish to have access to the raw resource payload as well as the parsed value for any reason, you may also add parameters which have been annotated with the [@ResourceParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ResourceParam.html) of type `String` (to access the raw resource body) and/or `EncodingEnum` (to determine which encoding was used).
The following example shows how to use these additional data elements.
@ -134,7 +134,7 @@ If a client performs a contention aware update, the ETag version will be placed
# Instance Level - Delete
The [delete](http://hl7.org/implement/standards/fhir/http.html#delete) operation retrieves a specific version of a resource with a given ID. It takes a single ID parameter annotated with an [@IdParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) annotation, which supplies the ID of the resource to delete.
The [delete](http://hl7.org/implement/standards/fhir/http.html#delete) operation retrieves a specific version of a resource with a given ID. It takes a single ID parameter annotated with an [@IdParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) annotation, which supplies the ID of the resource to delete.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|delete}}
@ -143,7 +143,7 @@ The [delete](http://hl7.org/implement/standards/fhir/http.html#delete) operation
Delete methods are allowed to return the following types:
* **void**: This method may return `void`, in which case the server will return an empty response and the client will ignore any successful response from the server (failure responses will still throw an exception)
* **[MethodOutcome](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/api/MethodOutcome.html)**: This method may return a `MethodOutcome`, which is a wrapper for the FHIR OperationOutcome resource, which may optionally be returned by the server according to the FHIR specification.
* **[MethodOutcome](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/api/MethodOutcome.html)**: This method may return a `MethodOutcome`, which is a wrapper for the FHIR OperationOutcome resource, which may optionally be returned by the server according to the FHIR specification.
Example URL to invoke this method (HTTP DELETE):
@ -181,9 +181,9 @@ The following snippet shows how to define a patch method on a server:
The [create](http://hl7.org/implement/standards/fhir/http.html#create) operation saves a new resource to the server, allowing the server to give that resource an ID and version ID.
Create methods must be annotated with the [@Create](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Create.html) annotation, and have a single parameter annotated with the [@ResourceParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ResourceParam.html) annotation. This parameter contains the resource instance to be created. See the [@ResourceParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ResourceParam.html) for information on the types allowed for this parameter (resource types, String, byte[]).
Create methods must be annotated with the [@Create](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Create.html) annotation, and have a single parameter annotated with the [@ResourceParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ResourceParam.html) annotation. This parameter contains the resource instance to be created. See the [@ResourceParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ResourceParam.html) for information on the types allowed for this parameter (resource types, String, byte[]).
Create methods must return an object of type [MethodOutcome](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/api/MethodOutcome.html). This object contains the identity of the created resource.
Create methods must return an object of type [MethodOutcome](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/api/MethodOutcome.html). This object contains the identity of the created resource.
The following snippet shows how to define a server create method:
@ -208,7 +208,7 @@ The following snippet shows how the corresponding client interface would look:
The FHIR specification also allows "conditional creates". A conditional create has an additional header called `If-None-Exist` which the client will supply on the HTTP request. The client will populate this header with a search URL such as `Patient?identifier=foo`. See the FHIR specification for details on the semantics for correctly implementing conditional create.
When a conditional create is detected (i.e. when the create request contains a populated `If-None-Exist` header), if a method parameter annotated with the
[@ConditionalOperationParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ConditionalOperationParam.html) is detected, it will be populated with the value of this header.
[@ConditionalUrlParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ConditionalUrlParam.html) is detected, it will be populated with the value of this header.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|createConditional}}
@ -247,28 +247,28 @@ Searching is a very powerful and potentially very complicated operation to imple
The [validate](http://hl7.org/implement/standards/fhir/http.html#validate) operation tests whether a resource passes business validation, and would be acceptable for saving to a server (e.g. by a create or update method).
Validate methods must be annotated with the [@Validate](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Validate.html) annotation, and have a parameter annotated with the [@ResourceParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ResourceParam.html) annotation. This parameter contains the resource instance to be created.
Validate methods must be annotated with the [@Validate](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Validate.html) annotation, and have a parameter annotated with the [@ResourceParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ResourceParam.html) annotation. This parameter contains the resource instance to be created.
Validate methods may optionally also have a parameter of type IdType annotated with the [@IdParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) annotation. This parameter contains the resource ID (see the [FHIR specification](http://hl7.org/implement/standards/fhir/http.html#validation) for details on how this is used).
Validate methods may optionally also have a parameter of type IdType annotated with the [@IdParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) annotation. This parameter contains the resource ID (see the [FHIR specification](http://hl7.org/implement/standards/fhir/http.html#validation) for details on how this is used).
Validate methods must return normally if the resource validates successfully, or throw an [UnprocessableEntityException](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/server/exceptions/UnprocessableEntityException.html) or [InvalidRequestException](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/server/exceptions/InvalidRequestException.html) if the validation fails.
Validate methods must return normally if the resource validates successfully, or throw an [UnprocessableEntityException](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/server/exceptions/UnprocessableEntityException.html) or [InvalidRequestException](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/server/exceptions/InvalidRequestException.html) if the validation fails.
Validate methods must return either:
* **void** &ndash; The method should throw an exception for a validation failure, or return normally.
* An object of type [MethodOutcome](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/api/MethodOutcome.html). The MethodOutcome may optionally be populated with an OperationOutcome resource, which will be returned to the client if it exists.
* An object of type [MethodOutcome](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/api/MethodOutcome.html). The MethodOutcome may optionally be populated with an OperationOutcome resource, which will be returned to the client if it exists.
The following snippet shows how to define a server validate method:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|validate}}
```
In the example above, only the [@ResourceParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ResourceParam.html) parameter is technically required, but you may also add the following parameters:
In the example above, only the [@ResourceParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/ResourceParam.html) parameter is technically required, but you may also add the following parameters:
* **[@Validate.Mode](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Validate.html#Mode) ValidationModeEnum theMode** - This is the validation mode (see the FHIR specification for information on this)
* **[@Validate.Mode](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Validate.Mode.html) ValidationModeEnum theMode** - This is the validation mode (see the FHIR specification for information on this)
* **[@Validate.Profile](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Validate.html#Profile) String profile** - This is the profile to validate against (see the FHIR specification for more information on this)
* **[@Validate.Profile](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Validate.Profile.html) String profile** - This is the profile to validate against (see the FHIR specification for more information on this)
Example URL to invoke this method (this would be invoked using an HTTP POST, with a Parameters resource in the POST body):
@ -284,7 +284,7 @@ FHIR defines that a FHIR Server must be able to export a Capability Statement (f
The HAPI FHIR RESTful server will automatically export such a capability statement. See the [Server Capability Statement](./introduction.html#capabilities) documentation for more information.
If you wish to override this default behaviour by creating your own capability statement provider, you simply need to define a class with a method annotated using the [@Metadata](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Metadata.html) annotation.
If you wish to override this default behaviour by creating your own capability statement provider, you simply need to define a class with a method annotated using the [@Metadata](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Metadata.html) annotation.
An example provider is shown below.
@ -292,13 +292,13 @@ An example provider is shown below.
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|metadataProvider}}
```
To create a Client which can retrieve a Server's conformance statement is simple. First, define your Client Interface, using the [@Metadata](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Metadata.html) annotation:
To create a Client which can retrieve a Server's conformance statement is simple. First, define your Client Interface, using the [@Metadata](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Metadata.html) annotation:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|metadataClient}}
```
Then use the standard [REST Client](/docs/client/fooo) mechanism for instantiating a client:
You can then use the standard [Annotation Client](/docs/client/annotation_client.html) mechanism for instantiating a client:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|metadataClientUsage}}
@ -316,11 +316,11 @@ HAPI provides a skeleton for implementing this action, although most of the effo
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|transaction}}
```
Transaction methods require one parameter annotated with [@TransactionParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/TransactionParam.html), and that parameter may be of type [`List<IBaseResource>`](/apidocs/hapi-fhir-base/org/hl7/fhir/instance/model/api/IBaseResource.html) or [`Bundle`](/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/Bundle.html)`.
Transaction methods require one parameter annotated with [@TransactionParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/TransactionParam.html), and that parameter may be of type [`List<IBaseResource>`](/hapi-fhir/apidocs/hapi-fhir-base/org/hl7/fhir/instance/model/api/IBaseResource.html) or [`Bundle`](/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/Bundle.html)`.
In terms of actually implementing the method, unfortunately there is only so much help HAPI will give you. One might expect HAPI to automatically delegate the individual operations in the transaction to other methods on the server but at this point it does not do that. There is a lot that transaction needs to handle (making everything atomic, replacing placeholder IDs across multiple resources which may even be circular, handling operations in the right order) and so far we have not found a way for the framework to do this in a generic way.
What it comes down to is the fact that transaction is a tricky thing to implement. For what it's worth, you could look at the HAPI FHIR JPA Server [TransactionProcessor](/apidocs/hapi-fhir-jpaserver-base/ca/uhn/fhir/jpa/dao/TransactionProcessor.html) class for inspiration on how to build a transaction processor of your own (note that this class is tightly coupled with the rest of the JPA Server so it is unlikely that it can be used directly outside of that context).
What it comes down to is the fact that transaction is a tricky thing to implement. For what it's worth, you could look at the HAPI FHIR JPA Server [TransactionProcessor](/hapi-fhir/apidocs/hapi-fhir-jpaserver-base/ca/uhn/fhir/jpa/dao/TransactionProcessor.html) class for inspiration on how to build a transaction processor of your own (note that this class is tightly coupled with the rest of the JPA Server so it is unlikely that it can be used directly outside of that context).
Example URL to invoke this method (note that the URL is the base URL for the server, and the request body is a Bundle resource):
@ -347,20 +347,20 @@ Not yet implemented - Get in touch if you would like to help!
The [history](http://hl7.org/implement/standards/fhir/http.html#history) operation retrieves a historical collection of all versions of a single resource *(instance history)*, all resources of a given type *(type history)*, or all resources of any type on a server *(server history)*.
History methods are annotated with the [@History](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/History.html) annotation, and will have additional requirements depending on the kind of history method intended:
History methods are annotated with the [@History](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/History.html) annotation, and will have additional requirements depending on the kind of history method intended:
* For an **Instance History** method, the method must have a parameter annotated with the [@IdParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) annotation, indicating the ID of the resource for which to return history. The method must either be defined in a [resource provider](./resource_providers.html#resource-providers), or must have a `type()` value in the [@History](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/History.html) annotation if it is defined in a [plain provider](./resource_providers.html#plain-providers).
* For an **Instance History** method, the method must have a parameter annotated with the [@IdParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) annotation, indicating the ID of the resource for which to return history. The method must either be defined in a [resource provider](./resource_providers.html#resource-providers), or must have a `type()` value in the [@History](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/History.html) annotation if it is defined in a [plain provider](./resource_providers.html#plain-providers).
* For a **Type History** method, the method must not have any [@IdParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) parameter. The method must either be defined in a [resource provider](./resource_providers.html#resource-providers), or must have a `type()` value in the [@History](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/History.html) annotation if it is defined in a [plain provider](./resource_providers.html#plain-providers).
* For a **Type History** method, the method must not have any [@IdParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) parameter. The method must either be defined in a [resource provider](./resource_providers.html#resource-providers), or must have a `type()` value in the [@History](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/History.html) annotation if it is defined in a [plain provider](./resource_providers.html#plain-providers).
* For a **Server History** method, the method must not have any [@IdParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) parameter, and must not have a `type()` value specified in the [@History](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/History.html) annotation. The method must be defined in a [plain provider](./resource_providers.html#plain-providers).
* For a **Server History** method, the method must not have any [@IdParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) parameter, and must not have a `type()` value specified in the [@History](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/History.html) annotation. The method must be defined in a [plain provider](./resource_providers.html#plain-providers).
The following snippet shows how to define a history method on a server. Note that the following parameters are both optional, but may be useful in implementing the history operation:
* The [@Since](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Since.html) method argument implements the `_since` parameter and should be of type [DateTimeType](/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/DateTimeType.html).
* The [@Since](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Since.html) method argument implements the `_since` parameter and should be of type [DateTimeType](/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/DateTimeType.html).
* The [@At](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/At.html) method argument implements the `_at` parameter and may be of type [DateRangeParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/DateRangeParam.html) or [DateTimeType](/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/DateTimeType.html).
* The [@At](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/At.html) method argument implements the `_at` parameter and may be of type [DateRangeParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/DateRangeParam.html) or [DateTimeType](/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/DateTimeType.html).
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|history}}
@ -431,9 +431,9 @@ However, if you wish to add parameters to manually handle these fields, the foll
FHIR defines a mechanism for logically grouping resources together called [compartments](http://www.hl7.org/implement/standards/fhir/extras.html#compartment).
To define a search by compartment, you simply need to add the `compartmentName()` attribute to the [@Search](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Search.html) annotation, and add an [@IdParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) parameter.
To define a search by compartment, you simply need to add the `compartmentName()` attribute to the [@Search](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Search.html) annotation, and add an [@IdParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) parameter.
The following example shows a search method in a resource provider which returns a compartment. Note that you may also add [@RequiredParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/RequiredParam.html) and [@OptionalParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/OptionalParam.html) parameters to your compartment search method.
The following example shows a search method in a resource provider which returns a compartment. Note that you may also add [@RequiredParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/RequiredParam.html) and [@OptionalParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/OptionalParam.html) parameters to your compartment search method.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|searchCompartment}}

View File

@ -1,10 +1,10 @@
# REST Operations: Operations Framework
# REST Operations: Extended Operations
The FHIR specification defines a special kind of operations that have an RPC-like functionality. These are called "Execute Operations", or simply "Operations" throughout the FHIR specification.
A good introduction to this capability can be found on the [Operations Page](http://hl7.org/fhir/operations.html) of the FHIR Specification.
FHIR operations are a special type of RPC-style invocation you can perform against a FHIR server, type, or resource instance. These invocations are named using the convention `$name` (i.e. the name is prefixed with $) and will generally take a [Parameters](./apidocs-r4/org/hl7/fhir/r4/model/Parameters.html) resource as input and output. There are some cases where the input and/or output will be a different resource type however.
FHIR extended operations are a special type of RPC-style invocation you can perform against a FHIR server, type, or resource instance. These invocations are named using the convention `$name` (i.e. the name is prefixed with $) and will generally take a [Parameters](/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/Parameters.html) resource as input and output. There are some cases where the input and/or output will be a different resource type however.
## Providers
@ -12,7 +12,7 @@ To define an operation, a method should be placed in a [Resource Provider class]
# Type-Level Operations
To implement a type-specific operation, the method should be annotated with the [@Operation](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Operation.html) tag, and should have an [@OperationParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/OperationParam.html) tag for each named parameter that the input Parameters resource may be populated with. The following example shows how to implement the [`Patient/$everything`](http://hl7.org/fhir/operation-patient-everything.html) method, defined in the FHIR specification.
To implement a type-specific operation, the method should be annotated with the [@Operation](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Operation.html) tag, and should have an [@OperationParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/OperationParam.html) tag for each named parameter that the input Parameters resource may be populated with. The following example shows how to implement the [`Patient/$everything`](http://hl7.org/fhir/operation-patient-everything.html) method, defined in the FHIR specification.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ServerOperations.java|patientTypeOperation}}
@ -26,7 +26,7 @@ http://fhir.example.com/Patient/$everything
# Instance-Level Operations
To create an instance-specific operation (an operation which takes the ID of a specific resource instance as a part of its request URL), you can add a parameter annotated with the [@IdParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) annotation, of type [IdType](/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/IdType.html). The following example shows how to implement the `Patient/[id]/$everything` operation.
To create an instance-specific operation (an operation which takes the ID of a specific resource instance as a part of its request URL), you can add a parameter annotated with the [@IdParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IdParam.html) annotation, of type [IdType](/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/IdType.html). The following example shows how to implement the `Patient/[id]/$everything` operation.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ServerOperations.java|patientInstanceOperation}}
@ -65,12 +65,12 @@ To use a search parameter type, any of the search parameter types listed in [Res
Example URL to invoke this operation (HTTP request body is Parameters resource):
```url
http://fhir.example.com/$find-matches?date=2011-01-02&code=http://system|value
http://fhir.example.com/$find-matches?date=2011-01-02&code=http://system%7Cvalue
```
It is also fine to use collection types for search parameter types if you want to be able to accept multiple values. For example, a [`List<TokenParam>`](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/TokenParam.html) could be used if you want to allow multiple repetitions of a given token parameter (this is analogous to the "AND" semantics in a search).
It is also fine to use collection types for search parameter types if you want to be able to accept multiple values. For example, a [`List<TokenParam>`](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/TokenParam.html) could be used if you want to allow multiple repetitions of a given token parameter (this is analogous to the "AND" semantics in a search).
A [`TokenOrListParam`](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/TokenOrListParam.html) could be used if you want to allow multiple values within a single repetition, separated by comma (this is analogous to "OR" semantics in a search).
A [`TokenOrListParam`](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/TokenOrListParam.html) could be used if you want to allow multiple values within a single repetition, separated by comma (this is analogous to "OR" semantics in a search).
For example:
@ -80,7 +80,7 @@ For example:
# Returning Multiple OUT Parameters
In all of the Operation examples above, the return type specified for the operation is a single Resource instance. This is a common pattern in FHIR defined operations. However, it is also possible for an extended operation to be defined with multiple and/or repeating OUT parameters. In this case, you can return a [Parameters](/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/Parameters.html) resource directly.
In all of the Operation examples above, the return type specified for the operation is a single Resource instance. This is a common pattern in FHIR defined operations. However, it is also possible for an extended operation to be defined with multiple and/or repeating OUT parameters. In this case, you can return a [Parameters](/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/Parameters.html) resource directly.
# Accepting HTTP GET
@ -91,13 +91,13 @@ The FHIR specification allows for operations to be invoked using an HTTP GET ins
* The operation is marked as "affectsState = false". Note that early releases of the FHIR specification referred to an operation that did not affect state as "idempotent = true". It was subsequently determined that *idempotency* was the wrong term for the concept being expressed, but the term does persist in some HAPI FHIR documentation and code.
If you are implementing an operation which should allow HTTP GET, you should mark your operation with
`idempotent=true` in the [@Operation](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Operation.html). The default value for this flag is `false`, meaning that operations will not support <code>HTTP GET</code> by default.
`idempotent=true` in the [@Operation](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Operation.html). The default value for this flag is `false`, meaning that operations will not support <code>HTTP GET</code> by default.
Note that the HTTP GET form is only supported if the operation has only primitive parameters (no complex parameters or resource parameters). If a client makes a request containing a complex parameter, the server will respond with an <code>HTTP 405 Method Not Supported</code>.
# Manually handing Request/Response
For some operations you may wish to bypass the HAPI FHIR standard request parsing and/or response generation. In this case you may use the `manualRequest = true` and/or `manualResponse = true` attributes on the [@Operation](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Operation.html) annotation.
For some operations you may wish to bypass the HAPI FHIR standard request parsing and/or response generation. In this case you may use the `manualRequest = true` and/or `manualResponse = true` attributes on the [@Operation](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Operation.html) annotation.
The following example shows an operation that parses the request and generates a response (by echoing back the request).

View File

@ -18,11 +18,11 @@ http://fhir.example.com/Patient
# Search Parameters: String Introduction
To allow a search using given search parameters, add one or more parameters to your search method and tag these parameters as either [@RequiredParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/RequiredParam.html) or [@OptionalParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/OptionalParam.html).
To allow a search using given search parameters, add one or more parameters to your search method and tag these parameters as either [@RequiredParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/RequiredParam.html) or [@OptionalParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/OptionalParam.html).
This annotation takes a "name" parameter which specifies the parameter's name (as it will appear in the search URL). FHIR defines standardized parameter names for each resource, and these are available as constants on the individual HAPI resource classes.
Parameters which take a string as their format should use the [StringParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/StringParam.html) type. They may also use normal java `String`, although it is not possible to use modifiers such as the `:exact` modifier in that case.
Parameters which take a string as their format should use the [StringParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/StringParam.html) type. They may also use normal java `String`, although it is not possible to use modifiers such as the `:exact` modifier in that case.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|searchStringParam}}
@ -54,7 +54,7 @@ The FHIR specification provides a syntax for specifying dates+times (but for sim
Dates may be optionally prefixed with a qualifier. For example, the string `=ge2011-01-02` means any date on or after 2011-01-02.
To accept a qualified date parameter, use the [DateParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/DateParam.html) parameter type.
To accept a qualified date parameter, use the [DateParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/DateParam.html) parameter type.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|dates}}
@ -80,7 +80,7 @@ A common scenario in searches is to allow searching for resources with values (i
FHIR allows for multiple parameters with the same key, and interprets these as being an ***AND*** set. So, for example, a range of `&date=gt2011-01-01&date=lt2011-02-01` can be interpreted as any date within January 2011.
The following snippet shows how to accept such a range, and combines it with a specific identifier, which is a common scenario. (i.e. Give me a list of observations for a specific patient within a given date range). This is accomplished using a single parameter of type [DateRangeParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/DateRangeParam.html).
The following snippet shows how to accept such a range, and combines it with a specific identifier, which is a common scenario. (i.e. Give me a list of observations for a specific patient within a given date range). This is accomplished using a single parameter of type [DateRangeParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/DateRangeParam.html).
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|dateRange}}
@ -108,7 +108,7 @@ An example of this might be the following URL, which refers to any Observation r
http://fhir.example.com/Observation?subject.identifier=7000135&date=gt2011-01-01
```
When such a request is made of a server (or to make such a request from a client), the `getLowerBound()` or `getUpperBound()` property of the [DateRangeParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/DateRangeParam.html) object will be set to `null`.
When such a request is made of a server (or to make such a request from a client), the `getLowerBound()` or `getUpperBound()` property of the [DateRangeParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/DateRangeParam.html) object will be set to `null`.
# Search Parameters: Quantity
@ -130,12 +130,23 @@ http://fhir.example.com/Observation?value-quantity=lt123.2||mg|http://unitsofmea
Many search parameters refer to resource references. For instance, the Patient parameter "provider" refers to the resource marked as the managing organization for patients.
Reference parameters use the [ReferenceParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/ReferenceParam.html) type. Reference parameters are, in their most basic form, just a pointer to another resource. For example, you might want to query for DiagnosticReport resources where the subject (the Patient resource that the report is about) is Patient/123. The following example shows a simple resource reference parameter in use.
Reference parameters use the [ReferenceParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/ReferenceParam.html) type. Reference parameters are, in their most basic form, just a pointer to another resource. For example, you might want to query for DiagnosticReport resources where the subject (the Patient resource that the report is about) is Patient/123. The following example shows a simple resource reference parameter in use.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|referenceSimple}}
```
<a name="filter"/>
# Search Parameters: Filter
To implement the FHIR [_filter](http://hl7.org/fhir/search_filter.html) search style, you may create a parameter of type `StringParam` (or one of the and/or derivatives), as shown below.
```java
@OptionalParam(name=ca.uhn.fhir.rest.api.Constants.PARAM_FILTER)
StringAndListParam theFtFilter
```
# Chained Resource References
References may also support a "chained" value. This is a search parameter name on the target resource. For example, you might want to search for DiagnosticReport resources by subject, but use the subject's last name instead of their resource ID. In this example, you are chaining "family" (the last name) to "subject" (the patient).
@ -198,11 +209,11 @@ http://fhir.example.com/Observation?name-value-date=PROCTIME$2001-02-02
# Combining Multiple Parameters
Search methods may take multiple parameters, and these parameters may (or may not) be optional. To add a second required parameter, annotate the parameter with [@RequiredParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/RequiredParam.html). To add an optional parameter (which will be passed in as `null` if no value is supplied), annotate the method with [@OptionalParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/OptionalParam.html).
Search methods may take multiple parameters, and these parameters may (or may not) be optional. To add a second required parameter, annotate the parameter with [@RequiredParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/RequiredParam.html). To add an optional parameter (which will be passed in as `null` if no value is supplied), annotate the method with [@OptionalParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/OptionalParam.html).
You may annotate a method with any combination of as many [@RequiredParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/RequiredParam.html) and as many [@OptionalParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/OptionalParam.html) parameters as you want. It is valid to have only [@RequiredParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/RequiredParam.html) parameters, or only [@OptionalParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/OptionalParam.html) parameters, or any combination of the two.
You may annotate a method with any combination of as many [@RequiredParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/RequiredParam.html) and as many [@OptionalParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/OptionalParam.html) parameters as you want. It is valid to have only [@RequiredParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/RequiredParam.html) parameters, or only [@OptionalParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/OptionalParam.html) parameters, or any combination of the two.
If you wish to create a server that can accept any combination of a large number of parameters, (this is how the various reference servers behave, as well as the [Public HAPI Test Server](http://hapi.fhir.org)). The easiest way to accomplish this is to simply create one method with all allowable parameters, each annotated as [@OptionalParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/OptionalParam.html).
If you wish to create a server that can accept any combination of a large number of parameters, (this is how the various reference servers behave, as well as the [Public HAPI Test Server](http://hapi.fhir.org)). The easiest way to accomplish this is to simply create one method with all allowable parameters, each annotated as [@OptionalParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/OptionalParam.html).
On the other hand, if you have specific combinations of parameters you wish to support (a common scenario if you are building FHIR on top of existing data sources and only have certain indexes you can use) you could create multiple search methods, each with specific required and optional parameters matching the database indexes.
@ -235,9 +246,9 @@ It is worth noting that according to the FHIR specification, you can have an AND
## OR Relationship Query Parameters
To accept a composite parameter, use a parameter type which implements the [IQueryParameterOr](/apidocs/hapi-fhir-base/ca/uhn/fhir/model/api/IQueryParameterOr.html) interface.
To accept a composite parameter, use a parameter type which implements the [IQueryParameterOr](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/model/api/IQueryParameterOr.html) interface.
Each parameter type ([StringParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/StringParam.html), [TokenParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/TokenParam.html), etc.) has a corresponding parameter which accepts an ***OR*** list of parameters. These types are called "[type]OrListParam", for example: [StringOrListParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/StringOrListParam.html) and [TokenOrListParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/TokenOrListParam.html).
Each parameter type ([StringParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/StringParam.html), [TokenParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/TokenParam.html), etc.) has a corresponding parameter which accepts an ***OR*** list of parameters. These types are called "[type]OrListParam", for example: [StringOrListParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/StringOrListParam.html) and [TokenOrListParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/TokenOrListParam.html).
The following example shows a search for Observation by name, where a list of names may be passed in (and the expectation is that the server will return Observations that match any of these names):
@ -253,7 +264,7 @@ http://fhir.example.com/Observation?name=urn:fakenames|123,urn:fakenames|456
## AND Relationship Query Parameters
To accept a composite parameter, use a parameter type which implements the [IQueryParameterAnd](/apidocs/hapi-fhir-base/ca/uhn/fhir/model/api/IQueryParameterAnd.html) interface (which in turn encapsulates the corresponding IQueryParameterOr types).
To accept a composite parameter, use a parameter type which implements the [IQueryParameterAnd](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/model/api/IQueryParameterAnd.html) interface (which in turn encapsulates the corresponding IQueryParameterOr types).
An example follows which shows a search for Patients by address, where multiple string lists may be supplied by the client. For example, the client might request that the address match `("Montreal" OR "Sherbrooke") AND ("Quebec" OR "QC")` using the following query:
@ -261,7 +272,7 @@ An example follows which shows a search for Patients by address, where multiple
http://fhir.example.com/Patient?address=Montreal,Sherbrooke&address=Quebec,QC
```
The following code shows how to receive this parameter using a [StringAndListParameter](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/StringAndListParam.html), which can handle an AND list of multiple OR lists of strings.
The following code shows how to receive this parameter using a [StringAndListParameter](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/StringAndListParam.html), which can handle an AND list of multiple OR lists of strings.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|searchMultipleAnd}}
@ -272,7 +283,7 @@ in very specific cases where a composite parameter has been specifically defined
# AND Relationship Query Parameters for Dates
Dates are a special case, since it is a fairly common scenario to want to match a date range (which is really just an AND query on two qualified date parameters). See the section on [date ranges](#DATE_RANGES) for an example of a [DateRangeParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/DateRangeParam.html).
Dates are a special case, since it is a fairly common scenario to want to match a date range (which is really just an AND query on two qualified date parameters). See the section on [date ranges](#DATE_RANGES) for an example of a [DateRangeParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/DateRangeParam.html).
# Resource Includes (_include)
@ -298,7 +309,7 @@ It is also possible to use a String type for the include parameter, which is mor
# Reverse Resource Includes (_revinclude)
To add support for reverse includes (via the `_revinclude` parameter), use the same format as with the `_include` parameter (shown above) but add `reverse=true` to the [@IncludeParam](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IncludeParam.html) annotation, as shown below.
To add support for reverse includes (via the `_revinclude` parameter), use the same format as with the `_include` parameter (shown above) but add `reverse=true` to the [@IncludeParam](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/IncludeParam.html) annotation, as shown below.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|revInclude}}
@ -326,7 +337,7 @@ FHIR supports [sorting](http://www.hl7.org/implement/standards/fhir/search.html#
According to the specification, sorting is requested by the client using a search param as the sort key. For example, when searching Patient resources, a sort key of "given" requests the "given" search param as the sort key. That param maps to the values in the field "Patient.name.given".
Sort specifications can be passed into handler methods by adding a parameter of type [SortSpec](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/api/SortSpec.html), which has been annotated with the [@Sort](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Sort.html) annotation, as shown in the following example:
Sort specifications can be passed into handler methods by adding a parameter of type [SortSpec](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/api/SortSpec.html), which has been annotated with the [@Sort](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Sort.html) annotation, as shown in the following example:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|sort}}
@ -340,7 +351,7 @@ http://fhir.example.com/Patient?_identifier=urn:foo|123&_sort=given
# Adding Descriptions
It is also possible to annotate search methods and/or parameters with the [@Description](/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/annotation/Description.html) annotation. This annotation allows you to add a description of the method and the individual parameters. These descriptions will be placed in the server's conformance statement, which can be helpful to anyone who is developing software against your server.
It is also possible to annotate search methods and/or parameters with the [@Description](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/model/api/annotation/Description.html) annotation. This annotation allows you to add a description of the method and the individual parameters. These descriptions will be placed in the server's conformance statement, which can be helpful to anyone who is developing software against your server.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|searchWithDocs}}

View File

@ -38,4 +38,4 @@ To get started with the JPA Server, jump to [JPA Server Introduction](/docs/serv
For users in an environment where existing services using JAX-RS have been created, it is often desirable to use JAX-RS for FHIR servers as well. HAPI FHIR provides a JAX-RS FHIR server implementation for this purpose.
To get started with the JAX-RS FHIR Server, jump to [JAX-RS FHIR Server Introduction](/docs/server_jaxrs/introduction.html).
To get started with the JAX-RS FHIR Server, jump to [JAX-RS FHIR Server Introduction](/docs/server_plain/jax_rs.html).

View File

@ -0,0 +1,112 @@
# Web Testpage Overlay
HAPI FHIR includes a web UI that can be used to test your server implementation. This UI is the same UI used on the [http://hapi.fhir.org](http://hapi.fhir.org) public HAPI FHIR test server.
The Web Testpage Overlay is a [Maven WAR Overlay](http://maven.apache.org/plugins/maven-war-plugin/overlays.html) project,
meaning that you create your own WAR project (which you would likely be doing anyway
to create your server) and the overlay drops a number of files into your project. You can then selectively customize the system by replacing the built-in overlay files.
# Adding the Overlay
These instructions assume that you have an exsiting web project which uses Maven to build. The POM.xml should have a "packaging" type of "war".
Adding the overlay to your project is relatively simple. First, add the "hapi-fhir-testpage-overlay" dependency to the dependencies section of your POM.xml file.
```xml
<dependencies>
<!-- ... other dependencies ... -->
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-testpage-overlay</artifactId>
<version>${project.version}</version>
<type>war</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-testpage-overlay</artifactId>
<version>${project.version}</version>
<classifier>classes</classifier>
<scope>provided</scope>
</dependency>
</dependencies>
```
Then, add the following WAR plugin to the plugins section of your POM.xml
```xml
<build>
<plugins>
<!-- ... other plugins ... -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<overlays>
<overlay>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-testpage-overlay</artifactId>
</overlay>
</overlays>
</configuration>
</plugin>
</plugins>
</build>
```
Then, create a Java source file called `FhirTesterConfig.java` and copy in the following contents:
<macro name="snippet">
<param name="file" value="restful-server-example/src/main/java/ca/uhn/example/config/FhirTesterConfig.java" />
</macro>
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/FhirTesterConfig.java|file}}
```
Note that the URL in the file above must be customized to point to the FHIR endpoint your server will be deployed to. For example, if you are naming your project "myfhir-1.0.war" and your endpoint in the WAR is deployed to "/fhirbase/*" then you should put a URL similar to <code>http://localhost:8080/myfhir-1.0/fhirbase</code>
Next, create the following directory in your project if it doesn't already exist:
`src/main/webapp/WEB-INF</code>`
In this directory you should open your `web.xml` file, or create it if it doesn't exist. This file is required in order to deploy to a servlet container and you should create it if it does not already exist. Place the following contents in that file, adjusting the package on the <code>FhirTesterConfig</code> to match the actual package in which you placed this file.
```xml
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>ca.uhn.example.config.FhirTesterConfig</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/tester/*</url-pattern>
</servlet-mapping>
```
# Customizing the Overlay
The most important customization required is to set the FHIR server base URL in the Java configuration file described above.
Beyond this, the entire tester application is built from a number of [Thymeleaf](http://thymeleaf.org) template files, any of which can be replaced to create your own look and feel. All of the templates can be found in your built war (after running the Maven build), or in the target directory's staging area, in `WEB-INF/templates`. By placing a file with the same path/name in your `src/main/webapp/WEB-INF/templates` directory you can replace the built in template with your own file.
# A Complete Example
The [hapi-fhir-jpaserver-starter](https://github.com/hapifhir/hapi-fhir-jpaserver-starter) project contains a complete working example of the FHIR Tester as a part of its configuration. You may
wish to browse its source to see how this works. The example in that project includes an overlay file that overrides some of the basic branding in the base project as well.
# Authentication
The testing UI uses its own client to talk to your FHIR server. In other words, there are no special "hooks" which the tested uses to retrieve data from your server, it acts as an HTTP client just like any other client.
This does mean that if your server has any authorization requirements, you will need to configure the tester UI to meet those requirements. For example, if your server has been configured to require a HTTP Basic Auth header (e.g. <code>Authorization: Basic VVNFUjpQQVNT</code>) you need to configure the tester UI to send those credentials across when it is acting as a FHIR client.
This is done by providing your own implementation of the `ITestingUiClientFactory` interface. This interface takes in some details about the incoming request and produces a client.

View File

@ -82,6 +82,6 @@ Note that the path and exact filename of the terminology files will likely need
# Migrate Database
The `migrate-database` command may be used to Migrate a database schema when upgrading a <a href="./doc_jpa.html">HAPI FHIR JPA</a> project from one version of HAPI FHIR to another version.
The `migrate-database` command may be used to Migrate a database schema when upgrading a [HAPI FHIR JPA](/docs/server_jpa/introduction.html) project from one version of HAPI FHIR to another version.
See <a href="./doc_jpa.html#upgrading">Upgrading HAPI FHIR JPA</a> for information on how to use this command.
See [Upgrading HAPI FHIR JPA](/docs/server_jpa/upgrading.html) for information on how to use this command.

View File

@ -0,0 +1,14 @@
# Validation Introduction
This section contains details on several strategies for validating resources:
* **[Parser Error Handler](./parser_error_handler.html)** validation is validation at runtime during the parsing of a resource. It can be used to catch input data that is impossible to fit into the HAPI data model. For example, it can be used to throw exceptions or display error messages if a resource being parsed contains elements for which there are no appropriate fields in a HAPI data structure. This is useful in order to ensure that no data is being lost during parsing, but is less comprehensive than resource validation against raw text data.
Parser Validation is extremely fast and lightweight since it happens within the parser and has no dependencies to outside resources.
* **[Profile Validation](./profile_validator.html)** is validation of the raw or parsed resource against the official FHIR validation rules (ie. the official FHIR definitions, expressed as profile resources such as [StructureDefinition](http://hl7.org/fhir/structuredefinition.html) and [ValueSet](http://hl7.org/fhir/valueset.html).
Profile Validation can also be used to validate resources against individual Implementation Guides which derive from the core specification (e.g. the [US Core](http://hl7.com/uscore) implementation guide).
* **[Schema/Schematron Validation](./schema_validator.html)** is validation using XSD/SCH validation files provided by FHIR. This validator performs well but produces less usable error messages than Profile Validation.

View File

@ -0,0 +1,28 @@
# Parser Error Handler
Parser Error Handler validation is enabled by calling [IParser#setParserErrorHandler(IParserErrorHandler)](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/parser/IParser.html#setParserErrorHandler(ca.uhn.fhir.parser.IParserErrorHandler)) on either the FhirContext or on individual parser instances. This method takes an [IParserErrorHandler](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/parser/IParserErrorHandler.html), which is a callback that will be invoked any time a parse issue is detected.
There are two implementations of IParserErrorHandler that come built into HAPI FHIR. You can also supply your own implementation if you want.
* [**LenientErrorHandler**](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/parser/LenientErrorHandler.html) logs any errors but does not abort parsing. By default this handler is used, and it logs errors at "warning" level. It can also be configured to silently ignore issues. LenientErrorHandler is the default.
* [**StrictErrorHandler**](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/parser/StrictErrorHandler.html) throws a [DataFormatException](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/parser/DataFormatException.html) if any errors are detected.
The following example shows how to configure a parser to use strict validation.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ValidatorExamples.java|parserValidation}}
```
You can also configure the error handler at the FhirContext level, which is useful for clients.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ValidatorExamples.java|clientValidation}}
```
FhirContext level validators can also be useful on servers.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ValidatorExamples.java|serverValidation}}
```

View File

@ -0,0 +1,103 @@
# Profile Validator
# Validator Modules
HAPI provides a built-in and configurable mechanism for validating resources. This mechanism is called the *Resource Validator*.
The resource validator is an extendible and modular system, and you can configure it in a number of ways in order to get the specific type of validation you want to achieve.
The validator can be manually invoked at any time by creating a validator and configuring it with one or more [IValidatorModule](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/validation/IValidatorModule.html) instances.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ValidatorExamples.java|validationIntro}}
```
<div class="doc_info_bubble">
Note that in earlier releases of HAPI FHIR it was common to register different kinds of validator modules (such as [Schema/Schematron](./schema_validator.html)) because the FHIR Instance Validator module described below was not mature. This is no longer the case, and it is generally recommended to use the FHIR Instance Validator.
</div>
# FHIR Conformance Packages
There are a few key concepts worth explaining before getting into how validation is performed in HAPI FHIR.
Conformance Resources:
* [StructureDefinition](http://hl7.org/fhir/structuredefinition.html) &ndash; Contains definitions of the valid fields in a given resource, including details about their datatypes, min/max cardinalities, valid values, and other rules about what content is valid and what is not. StructureDefinition resources are also used to express derivative profiles (e.g. a description of a constraint on a FHIR resource for a specfic purpose) as well as to describe extensions.
* [CodeSystem](http://hl7.org/fhir/codesystem.html) &ndash; Contains definiitions of codes and vocabularies that can be used in FHIR resources, or even outside of FHIR resources.
* [ValueSet](http://hl7.org/fhir/valueset.html) &ndash; Contains lists of codes drawn from one or more CodeSystems that are suitable for use in a specific field in a FHIR resource.
# FHIR Instance Validator
HAPI has very complete support for validation against FHIR conformance resources.
This functionality is proviided by the HAPI FHIR "reference validator", which is able
to check a resource for conformance to FHIR profiles.
The FHIR instance validator is very powerful. It will use terminology services to validate codes, StructureDefinitions to validate semantics, and uses a customized XML/JSON parser in order to provide descriptive error messages.
It is always worth considering the performance implications of using the Instance Validator at runtime in a production system. While efforts are made to keep the Instance Validator and its supporting infrastructure performant, the act of performing deep semantic validation is never going to be without some performance cost.
The FHIR instance validator can be used to validate a resource against the
official structure definitions (produced by HL7) as well as against custom
definitions provided either by HL7 or by the user.
# Running the Validator
<div class="doc_info_bubble">
<b>Note on FHIR Versions:</b> Many of the classes described on this page have
multiple versions, and you should use the version of the class the is appropriate
for the version of FHIR you are looking to validate. For example, the
examples and links below are using the
<code>org.hl7.fhir.r4.hapi.validation.FhirInstanceValidator</code> class to
validate FHIR R4 resources, but you would want to use the class
<code>org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator</code>
if you need to validate DSTU3 content.
</div>
To execute the validator, you simply create an instance of [FhirInstanceValidator](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/r4/hapi/validation/FhirInstanceValidator.html) and register it to new validator, as shown in the example below.
Note that the example below uses the official FHIR StructureDefintions and ValueSets
to validate the resource. It will not work unless you include the
**hapi-fhir-validation-resources-[version].jar** module/JAR on your classpath.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ValidatorExamples.java|instanceValidator}}
```
# Supplying Your Own Definitions
The FhirInstanceValidator relies on an implementation of an interface called [IValidationSupport](/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/hapi/ctx/IValidationSupport.html) interface to load StructureDefinitions, validate codes, etx.
By default, an implementation of this interface called [DefaultProfileValidationSupport](/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/hapi/ctx/DefaultProfileValidationSupport.html) is used. This implementation simply uses the built-in official FHIR definitions to validate against (and in many cases, this is good enough).
However, if you have needs beyond simply validating against the core FHIR specification, you may wish to use something more.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ValidatorExamples.java|validateSupplyProfiles}}
```
# Buiilt-In Validation Support Classes
There are a several implementations of the [IValidationSupport](/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/hapi/ctx/IValidationSupport.html) interface built into HAPI FHIR that can be used, typically in a chain.
* [**DefaultProfileValidationSupport**](/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/hapi/ctx/DefaultProfileValidationSupport.html) - Supplies the built-in FHIR core structure definitions, including both structures and vocabulary.
* [**ValidationSupportChain**](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/r4/hapi/validation/ValidationSupportChain.html) - Can be used to chain multiple implementations together so that for every request, each support class instance in the chain is tried in sequence.
* [**PrePopulatedValidationSupport**](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/r4/hapi/validation/PrePopulatedValidationSupport.html) - Contains a series of HashMaps that store loaded conformance resources in memory. Typically this is initialized at startup in order to add custom conformance resources into the chain.
* [**PrePopulatedValidationSupport**](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/r4/hapi/validation/PrePopulatedValidationSupport.html) - Contains a series of HashMaps that store loaded conformance resources in memory. Typically this is initialized at startup in order to add custom conformance resources into the chain.
* [**CachingValidationSupport**](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/r4/hapi/validation/CachingValidationSupport.html) - Caches results of calls to a wrapped service implementation for a period of time. This class can be a significant help in terms of performance if you are loading conformance resources or performing terminology operations from a database or disk.
* [**SnapshotGeneratingValidationSupport**](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/r4/hapi/validation/SnapshotGeneratingValidationSupport.html) - Generates StructureDefinition snapshots as needed. This should be added to your chain if you are working wiith differential StructueDefinitions that do not include the snapshot view.

View File

@ -0,0 +1,28 @@
# Schema / Schematron Validator
FHIR resource definitions are distributed with a set of XML schema files (XSD) as well as a set of XML Schematron (SCH) files. These two sets of files are complimentary to each other, meaning that in order to claim compliance to the FHIR specification, your resources must validate against both sets.
The two sets of files are included with HAPI, and it uses them to perform validation.
# Preparation
In order to use HAPI's Schematron support, a libaray called [Ph-Schematron](https://github.com/phax/ph-schematron) is used, so this library must be added to your classpath (or Maven POM file, Gradle file, etc.)
Note that this library is specified as an optional dependency by HAPI FHIR so you need to explicitly include it if you want to use this functionality.
# Validating a Resource
To validate a resource instance, a new validator instance is requested from the FHIR Context. This validator is then applied against a specific resource instance, as shown in the example below.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ValidatorExamples.java|basicValidation}}
```
## Validating a Set of Files
The following example shows how to load a set of resources from files on disk and validate each one.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ValidatorExamples.java|validateFiles}}
```

View File

@ -67,7 +67,8 @@ public class DaoConfig {
* <li>message</li>
* </ul>
*/
private static final Set<String> DEFAULT_BUNDLE_TYPES_ALLOWED_FOR_STORAGE = Collections.unmodifiableSet(new TreeSet<>(Sets.newHashSet(
@SuppressWarnings("WeakerAccess")
public static final Set<String> DEFAULT_BUNDLE_TYPES_ALLOWED_FOR_STORAGE = Collections.unmodifiableSet(new TreeSet<>(Sets.newHashSet(
Bundle.BundleType.COLLECTION.toCode(),
Bundle.BundleType.DOCUMENT.toCode(),
Bundle.BundleType.MESSAGE.toCode()

View File

@ -24,37 +24,42 @@ import org.hibernate.annotations.Immutable;
import org.hibernate.annotations.Subselect;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.io.Serializable;
@Entity
@Immutable
@Subselect(
"SELECT CONCAT(vsc.PID, ' ', vscd.PID) AS PID, " +
" vsc.PID AS CONCEPT_PID, " +
" vsc.VALUESET_PID AS CONCEPT_VALUESET_PID, " +
" vsc.VALUESET_ORDER AS CONCEPT_VALUESET_ORDER, " +
" vsc.SYSTEM_URL AS CONCEPT_SYSTEM_URL, " +
" vsc.CODEVAL AS CONCEPT_CODEVAL, " +
" vsc.DISPLAY AS CONCEPT_DISPLAY, " +
" vscd.PID AS DESIGNATION_PID, " +
" vscd.LANG AS DESIGNATION_LANG, " +
" vscd.USE_SYSTEM AS DESIGNATION_USE_SYSTEM, " +
" vscd.USE_CODE AS DESIGNATION_USE_CODE, " +
" vscd.USE_DISPLAY AS DESIGNATION_USE_DISPLAY, " +
" vscd.VAL AS DESIGNATION_VAL " +
"FROM TRM_VALUESET_CONCEPT vsc " +
" LEFT OUTER JOIN TRM_VALUESET_C_DESIGNATION vscd ON vsc.PID = vscd.VALUESET_CONCEPT_PID"
/*
* Note about the CONCAT function below- We need a primary key (an @Id) column
* because hibernate won't allow the view the function without it, but
*/
"SELECT CONCAT(vsc.PID, CONCAT(' ', vscd.PID)) AS PID, " +
" vsc.PID AS CONCEPT_PID, " +
" vsc.VALUESET_PID AS CONCEPT_VALUESET_PID, " +
" vsc.VALUESET_ORDER AS CONCEPT_VALUESET_ORDER, " +
" vsc.SYSTEM_URL AS CONCEPT_SYSTEM_URL, " +
" vsc.CODEVAL AS CONCEPT_CODEVAL, " +
" vsc.DISPLAY AS CONCEPT_DISPLAY, " +
" vscd.PID AS DESIGNATION_PID, " +
" vscd.LANG AS DESIGNATION_LANG, " +
" vscd.USE_SYSTEM AS DESIGNATION_USE_SYSTEM, " +
" vscd.USE_CODE AS DESIGNATION_USE_CODE, " +
" vscd.USE_DISPLAY AS DESIGNATION_USE_DISPLAY, " +
" vscd.VAL AS DESIGNATION_VAL " +
"FROM TRM_VALUESET_CONCEPT vsc " +
"LEFT OUTER JOIN TRM_VALUESET_C_DESIGNATION vscd ON vsc.PID = vscd.VALUESET_CONCEPT_PID"
)
public class TermValueSetConceptView implements Serializable {
private static final long serialVersionUID = 1L;
private static final int MAX_LENGTH = 500;
@Id
@Column(name="PID", length = MAX_LENGTH)
private String myPid;
@Column(name="PID", length = 1000 /* length only needed to satisfy JpaEntityTest, it's not used*/)
private String id; // still set automatically
@Column(name = "CONCEPT_PID")
private Long myConceptPid;

View File

@ -120,6 +120,28 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test {
}
@Test
public void testExpandTermValueSetAndChildren2() throws Exception {
myDaoConfig.setPreExpandValueSets(true);
CodeSystem codeSystem = loadResource(myFhirCtx, CodeSystem.class, "/r4/CodeSystem-iar-chymh-cb-calculated-cap-10.xml");
myCodeSystemDao.create(codeSystem);
ValueSet valueSet = loadResource(myFhirCtx, ValueSet.class, "/r4/ValueSet-iar-chymh-cb-calculated-cap-10.xml");
myValueSetDao.create(valueSet);
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
myCaptureQueriesListener.clear();
ValueSet expandedValueSet = myTermSvc.expandValueSet(valueSet, 0, 100);
ourLog.info("Expanded ValueSet:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expandedValueSet));
assertEquals(3, expandedValueSet.getExpansion().getContains().size());
}
@Test
public void testExpandExistingValueSetNotPreExpanded() throws Exception {
loadAndPersistCodeSystemAndValueSetWithDesignations(HttpVerb.POST);

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<CodeSystem xmlns="http://hl7.org/fhir">
<id value="chymh-cb-calculated-cap-10"/>
<url value="http://ccim.on.ca/fhir/iar/CodeSystem/chymh-cb-calculated-cap-10"/>
<version value="0.1"/>
<name value="CYMH Interpersonal Conflict CAP"/>
<status value="draft"/>
<date value="2019-08-08"/>
<publisher value="CCIM"/>
<contact>
<telecom>
<system value="other"/>
<value value="https://www.ccim.on.ca"/>
</telecom>
</contact>
<caseSensitive value="true"/>
<compositional value="false"/>
<content value="complete"/>
<concept>
<code value="0"/>
<display value="Not Triggered"/>
</concept>
<concept>
<code value="1"/>
<display value="Triggered to reduce conflict within a specific domain"/>
</concept>
<concept>
<code value="2"/>
<display value=" Triggered to reduce widespread conflict"/>
</concept>
</CodeSystem>

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<ValueSet xmlns="http://hl7.org/fhir">
<id value="chymh-cb-calculated-cap-10"/>
<url value="http://ccim.on.ca/fhir/iar/ValueSet/chymh-cb-calculated-cap-10"/>
<version value="0.1"/>
<name value="CYMH Interpersonal Conflict CAP"/>
<status value="draft"/>
<date value="2019-08-08"/>
<publisher value="CCIM"/>
<contact>
<telecom>
<system value="other"/>
<value value="https://www.ccim.on.ca"/>
</telecom>
</contact>
<compose>
<include>
<system value="http://ccim.on.ca/fhir/iar/CodeSystem/chymh-cb-calculated-cap-10"/>
<version value="0.1"/>
<concept>
<code value="0"/>
<display value="Not Triggered"/>
</concept>
<concept>
<code value="1"/>
<display value="Triggered to reduce conflict within a specific domain"/>
</concept>
<concept>
<code value="2"/>
<display value=" Triggered to reduce widespread conflict"/>
</concept>
</include>
</compose>
</ValueSet>

View File

@ -24,6 +24,8 @@ import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
import org.intellij.lang.annotations.Language;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.support.TransactionTemplate;
@ -47,6 +49,7 @@ public abstract class BaseTask<T extends BaseTask> {
private boolean myDryRun;
private List<ExecutedStatement> myExecutedStatements = new ArrayList<>();
private boolean myNoColumnShrink;
private boolean myFailureAllowed;
private final String myProductVersion;
private final String mySchemaVersion;
@ -101,9 +104,19 @@ public abstract class BaseTask<T extends BaseTask> {
if (isDryRun() == false) {
Integer changes = getConnectionProperties().getTxTemplate().execute(t -> {
JdbcTemplate jdbcTemplate = getConnectionProperties().newJdbcTemplate();
int changesCount = jdbcTemplate.update(theSql, theArguments);
try {
int changesCount = jdbcTemplate.update(theSql, theArguments);
logInfo(ourLog, "SQL \"{}\" returned {}", theSql, changesCount);
return changesCount;
return changesCount;
} catch (DataAccessException e) {
if (myFailureAllowed) {
ourLog.info("Task did not exit successfully, but task is allowed to fail");
ourLog.debug("Error was: {}", e.getMessage(), e);
return 0;
} else {
throw e;
}
}
});
myChangesCount += changes;
@ -144,6 +157,10 @@ public abstract class BaseTask<T extends BaseTask> {
public abstract void execute() throws SQLException;
public void setFailureAllowed(boolean theFailureAllowed) {
myFailureAllowed = theFailureAllowed;
}
public String getFlywayVersion() {
String releasePart = myProductVersion;
if (releasePart.startsWith("V")) {

View File

@ -61,13 +61,18 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
protected void init410() { // 20190815 - present
Builder version = forVersion(VersionEnum.V4_1_0);
version.onTable("HFJ_SPIDX_NUMBER").modifyColumn("20190920.1", "RES_ID").nonNullable().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
version.onTable("HFJ_SPIDX_COORDS").modifyColumn("20190920.2", "RES_ID").nonNullable().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
version.onTable("HFJ_SPIDX_TOKEN").modifyColumn("20190920.3", "RES_ID").nonNullable().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
version.onTable("HFJ_SPIDX_STRING").modifyColumn("20190920.4", "RES_ID").nonNullable().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
version.onTable("HFJ_SPIDX_DATE").modifyColumn("20190920.5", "RES_ID").nonNullable().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
version.onTable("HFJ_SPIDX_QUANTITY").modifyColumn("20190920.6", "RES_ID").nonNullable().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
version.onTable("HFJ_SPIDX_URI").modifyColumn("20190920.7", "RES_ID").nonNullable().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
/*
* Note: The following tasks are markes as failure allowed - This is because all we're
* doing is setting a not-null on a column that will never be null anyway. Setting not null
* fails on SQL Server because there is an index on this column... Which is dumb, but hey.
*/
version.onTable("HFJ_SPIDX_NUMBER").modifyColumn("20190920.1", "RES_ID").nonNullable().failureAllowed().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
version.onTable("HFJ_SPIDX_COORDS").modifyColumn("20190920.2", "RES_ID").nonNullable().failureAllowed().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
version.onTable("HFJ_SPIDX_TOKEN").modifyColumn("20190920.3", "RES_ID").nonNullable().failureAllowed().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
version.onTable("HFJ_SPIDX_STRING").modifyColumn("20190920.4", "RES_ID").nonNullable().failureAllowed().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
version.onTable("HFJ_SPIDX_DATE").modifyColumn("20190920.5", "RES_ID").nonNullable().failureAllowed().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
version.onTable("HFJ_SPIDX_QUANTITY").modifyColumn("20190920.6", "RES_ID").nonNullable().failureAllowed().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
version.onTable("HFJ_SPIDX_URI").modifyColumn("20190920.7", "RES_ID").nonNullable().failureAllowed().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
// HFJ_SEARCH
version.onTable("HFJ_SEARCH").addColumn("20190921.1", "EXPIRY_OR_NULL").nullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.DATE_TIMESTAMP);

View File

@ -196,7 +196,7 @@ public class Builder {
/**
* @param theOldName The old column name
* @param theNewName The new column name
* @param isOkayIfNeitherColumnExists Setting this to true means that it's not an error if neither column exists
* @param isOkayIfNeitherColumnExists Setting this to true means that it's not an error if neither column exists
* @param theDeleteTargetColumnFirstIfBothExist Setting this to true causes the migrator to be ok with the target column existing. It will make sure that there is no data in the column with the new name, then delete it if so in order to make room for the renamed column. If there is data it will still bomb out.
*/
public BuilderWithTableName renameColumn(String theVersion, String theOldName, String theNewName, boolean isOkayIfNeitherColumnExists, boolean theDeleteTargetColumnFirstIfBothExist) {
@ -279,6 +279,7 @@ public class Builder {
public class BuilderModifyColumnWithNameAndNullable {
private final String myVersion;
private final boolean myNullable;
private boolean myFailureAllowed;
public BuilderModifyColumnWithNameAndNullable(String theVersion, boolean theNullable) {
myVersion = theVersion;
@ -308,8 +309,14 @@ public class Builder {
}
task.setNullable(myNullable);
task.setColumnType(theColumnType);
task.setFailureAllowed(myFailureAllowed);
addTask(task);
}
public BuilderModifyColumnWithNameAndNullable failureAllowed() {
myFailureAllowed = true;
return this;
}
}
}

View File

@ -1,7 +1,9 @@
package ca.uhn.fhir.jpa.migrate.taskdef;
import ca.uhn.fhir.jpa.migrate.JdbcUtils;
import org.flywaydb.core.internal.command.DbMigrate;
import org.junit.Test;
import org.springframework.dao.DataIntegrityViolationException;
import java.sql.SQLException;
@ -213,4 +215,43 @@ public class ModifyColumnTest extends BaseTest {
assertThat(JdbcUtils.getColumnNames(getConnectionProperties(), "SOMETABLE"), containsInAnyOrder("PID", "TEXTCOL"));
}
@Test
public void testFailureAllowed() throws SQLException {
executeSql("create table SOMETABLE (PID bigint, TEXTCOL varchar(255))");
executeSql("insert into SOMETABLE (TEXTCOL) values ('HELLO')");
ModifyColumnTask task = new ModifyColumnTask("1", "1");
task.setTableName("SOMETABLE");
task.setColumnName("TEXTCOL");
task.setColumnType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
task.setNullable(true);
task.setFailureAllowed(true);
getMigrator().addTask(task);
getMigrator().migrate();
assertEquals(BaseTableColumnTypeTask.ColumnTypeEnum.STRING, JdbcUtils.getColumnType(getConnectionProperties(), "SOMETABLE", "TEXTCOL").getColumnTypeEnum());
}
@Test
public void testFailureNotAllowed() throws SQLException {
executeSql("create table SOMETABLE (PID bigint, TEXTCOL varchar(255))");
executeSql("insert into SOMETABLE (TEXTCOL) values ('HELLO')");
ModifyColumnTask task = new ModifyColumnTask("1", "1");
task.setTableName("SOMETABLE");
task.setColumnName("TEXTCOL");
task.setColumnType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
task.setNullable(true);
getMigrator().addTask(task);
try {
getMigrator().migrate();
fail();
} catch (DbMigrate.FlywayMigrateException e) {
// expected
}
}
}

View File

@ -74,6 +74,16 @@
<artifactId>Saxon-HE</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>xpp3</groupId>
<artifactId>xpp3</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.fhir</groupId>
<artifactId>ucum</artifactId>
<optional>true</optional>
</dependency>
<!-- Testing -->
<dependency>
@ -303,6 +313,16 @@
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<includeDependencySources>true</includeDependencySources>
<dependencySourceIncludes>
<include>ca.uhn.hapi.fhir:org.hl7.fhir.dstu2</include>
</dependencySourceIncludes>
</configuration>
</plugin>
</plugins>
</build>

View File

@ -21,7 +21,7 @@ import java.util.List;
/**
* Simple validation support module that handles profile snapshot generation. This is
* separate from other funcrtions since it needs a link to a validation support
* separate from other functions since it needs a link to a validation support
* module itself, and it is useful to be able to pass a chain in.
*/
public class SnapshotGeneratingValidationSupport implements IValidationSupport {

View File

@ -46,6 +46,10 @@
database migration tasks that have already been applied. The hapi-fhir-cli migrate tool has been changed
to use flyway. Learn more about flyway here: https://flywaydb.org/.
</action>
<action type="fix" issue="1613">
ValueSet Precalculation sometimes failed on Oracle DBs due to an invalid SQL function. This
has been corrected.
</action>
</release>
<release version="4.1.0" date="2019-11-13" description="Jitterbug">
<action type="add">

View File

@ -1,256 +1,258 @@
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<properties>
<title>Resource References</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<!-- The body of the document contains a number of sections -->
<section name="Resource References">
<p>
Resource references are a key part of the HAPI FHIR model,
since almost any resource will have references to other resources
within it.
</p>
<p>
The <a href="http://jamesagnew.github.io/hapi-fhir/apidocs/ca/uhn/fhir/model/dstu/composite/ResourceReferenceDt.html">ResourceReferenceDt</a>
type is the datatype for references. This datatype has a number of properties which help
make working with FHIR simple.
</p>
<p>
The <code>getReference()</code> method returns an IdDt instance which contains the identity of the
resource being referenced. This is the item which is most commonly populated when
interacting with FHIR. For example, consider the following Patient resource, which
contains a reference to an Organization resource:
</p>
<source><![CDATA[<Patient xmlns="http://hl7.org/fhir">
<identifier>
<system value="urn:mrns"/>
<value value="253345"/>
</identifier>
<managingOrganization>
<reference value="Organization/112"/>
</managingOrganization>
</Patient>]]></source>
<p>
Given a Patient resource obtained by invoking a client operation, a call to
<code>IdDt ref = patient.getManagingOrganization().getReference();</code>
returns an instance of IdDt which contains the "Organization/112" reference.
</p>
<p>
ResourceReferenceDt also has a field for storing actual resource instances however,
and this can be very useful.
</p>
</section>
<section name="References in Client Code">
<p>
In client code, if a resource reference refers to a resource which was received as a
part of the same response, <code>getResource()</code> will be populated with the
actual resource. This can happen because either the resource was received as a
contained resource, or the resource was received as a separate resource in a bundle.
</p>
</section>
<section name="References in Server Code">
<p>
In server code, you will often want to return a resource which contains
a link to another resource. Generally these "linked" resources are
not actually included in the response, but rather a link to the
resource is included and the client may request that resource directly
(by ID) if it is needed.
</p>
<p>
The following example shows a Patient resource being created which will have a
link to its managing organization when encoded from a server:
</p>
<source><![CDATA[Patient patient = new Patient();
patient.setId("Patient/1333");
patient.addIdentifier("urn:mrns", "253345");
patient.getManagingOrganization().setReference("Organization/124362");]]></source>
<subsection name="Handling Includes (_include) in a Bundle">
<p>
Your server code may also wish to add additional resource to a bundle
being returned (e.g. because of an _include directive in the client's request).
</p>
<p>
To do this, you can implement your server method to simply return
<code>List&lt;IResource&gt;</code> and then simply add your extra resources to
the list. Another technique however, is to populate the reference as shown
in the example below, but ensure that the referenced resource has an ID set.
</p>
<p>
In the following example, the Organization resource has an ID set, so it will not
be contained but will rather appear as a distinct entry in any returned
bundles. Both resources are added to a bundle, which will then have
two entries:
</p>
<macro name="snippet">
<param name="id" value="addIncludes" />
<param name="file" value="examples/src/main/java/example/IncludesExamples.java" />
</macro>
<p>
This will give the following output:
</p>
<source><![CDATA[<Bundle xmlns="http://hl7.org/fhir">
<id value="4e151274-2b19-4930-97f2-8427167a176c"/>
<type value="searchset"/>
<total value="1"/>
<link>
<relation value="fhir-base"/>
<url value="http://example.com/base"/>
</link>
<link>
<relation value="self"/>
<url value="http://example.com/base/Patient"/>
</link>
<entry>
<resource>
<Patient xmlns="http://hl7.org/fhir">
<id value="1333"/>
<identifier>
<system value="urn:mrns"/>
<value value="253345"/>
</identifier>
<managingOrganization>
<reference value="Organization/65546"/>
</managingOrganization>
</Patient>
</resource>
</entry>
<entry>
<resource>
<Organization xmlns="http://hl7.org/fhir">
<id value="65546"/>
<name value="Test Organization"/>
</Organization>
</resource>
<search>
<mode value="include"/>
</search>
</entry>
</Bundle>
]]></source>
</subsection>
<subsection name="Contained Resources">
<p>
On the other hand, if the linked resource
does not have an ID set, the linked resource will
be included in the returned bundle as a "contained" resource. In this
case, HAPI itself will define a local reference ID (e.g. "#1").
</p>
<source><![CDATA[// Create an organization, note that the organization does not have an ID
Organization org = new Organization();
org.getName().setValue("Contained Test Organization");
// Create a patient
Patient patient = new Patient();
patient.setId("Patient/1333");
patient.addIdentifier("urn:mrns", "253345");
// Put the organization as a reference in the patient resource
patient.getManagingOrganization().setResource(org);
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
System.out.println(encoded);]]></source>
<p>
This will give the following output:
</p>
<source><![CDATA[<Patient xmlns="http://hl7.org/fhir">
<contained>
<Organization xmlns="http://hl7.org/fhir" id="1">
<name value="Contained Test Organization"/>
</Organization>
</contained>
<identifier>
<system value="urn:mrns"/>
<value value="253345"/>
</identifier>
<managingOrganization>
<reference value="#1"/>
</managingOrganization>
</Patient>]]></source>
</subsection>
<p>
Note that you may also "contain" resources manually in your own code if you
prefer. The following example show how to do this:
</p>
<macro name="snippet">
<param name="id" value="manualContained" />
<param name="file" value="examples/src/main/java/example/ResourceRefs.java" />
</macro>
</section>
<section name="Versioned References">
<p>
By default, HAPI will strip resource versions from references between resources.
For example, if you set a reference to <code>Patient.managingOrganization</code>
to the value <code>Patient/123/_history/2</code>, HAPI will encode this
reference as <code>Patient/123</code>.
</p>
<p>
This is because in most circumstances, references between resources should be
versionless (e.g. the reference just points to the latest version, whatever
version that might be).
</p>
<p>
There are valid circumstances however for wanting versioned references. If you
need HAPI to emit versionned references, you have a few options:
</p>
<p>
You can force the parser to never strip versions:
</p>
<macro name="snippet">
<param name="id" value="disableStripVersions" />
<param name="file" value="examples/src/main/java/example/Parser.java" />
</macro>
<p>
You can also disable this behaviour entirely on the context (so that it
will apply to all parsers):
</p>
<macro name="snippet">
<param name="id" value="disableStripVersionsCtx" />
<param name="file" value="examples/src/main/java/example/Parser.java" />
</macro>
<p>
You can also configure HAPI to not strip versions only on certain fields. This
is desirable if you want versionless references in most places but need them
in some places:
</p>
<macro name="snippet">
<param name="id" value="disableStripVersionsField" />
<param name="file" value="examples/src/main/java/example/Parser.java" />
</macro>
</section>
</body>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<!-- Content has been migrated -->
<properties>
<title>Resource References</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<!-- The body of the document contains a number of sections -->
<section name="Resource References">
<p>
Resource references are a key part of the HAPI FHIR model,
since almost any resource will have references to other resources
within it.
</p>
<p>
The <a href="http://jamesagnew.github.io/hapi-fhir/apidocs/ca/uhn/fhir/model/dstu/composite/ResourceReferenceDt.html">ResourceReferenceDt</a>
type is the datatype for references. This datatype has a number of properties which help
make working with FHIR simple.
</p>
<p>
The <code>getReference()</code> method returns an IdDt instance which contains the identity of the
resource being referenced. This is the item which is most commonly populated when
interacting with FHIR. For example, consider the following Patient resource, which
contains a reference to an Organization resource:
</p>
<source><![CDATA[<Patient xmlns="http://hl7.org/fhir">
<identifier>
<system value="urn:mrns"/>
<value value="253345"/>
</identifier>
<managingOrganization>
<reference value="Organization/112"/>
</managingOrganization>
</Patient>]]></source>
<p>
Given a Patient resource obtained by invoking a client operation, a call to
<code>IdDt ref = patient.getManagingOrganization().getReference();</code>
returns an instance of IdDt which contains the "Organization/112" reference.
</p>
<p>
ResourceReferenceDt also has a field for storing actual resource instances however,
and this can be very useful.
</p>
</section>
<section name="References in Client Code">
<p>
In client code, if a resource reference refers to a resource which was received as a
part of the same response, <code>getResource()</code> will be populated with the
actual resource. This can happen because either the resource was received as a
contained resource, or the resource was received as a separate resource in a bundle.
</p>
</section>
<section name="References in Server Code">
<p>
In server code, you will often want to return a resource which contains
a link to another resource. Generally these "linked" resources are
not actually included in the response, but rather a link to the
resource is included and the client may request that resource directly
(by ID) if it is needed.
</p>
<p>
The following example shows a Patient resource being created which will have a
link to its managing organization when encoded from a server:
</p>
<source><![CDATA[Patient patient = new Patient();
patient.setId("Patient/1333");
patient.addIdentifier("urn:mrns", "253345");
patient.getManagingOrganization().setReference("Organization/124362");]]></source>
<subsection name="Handling Includes (_include) in a Bundle">
<p>
Your server code may also wish to add additional resource to a bundle
being returned (e.g. because of an _include directive in the client's request).
</p>
<p>
To do this, you can implement your server method to simply return
<code>List&lt;IResource&gt;</code> and then simply add your extra resources to
the list. Another technique however, is to populate the reference as shown
in the example below, but ensure that the referenced resource has an ID set.
</p>
<p>
In the following example, the Organization resource has an ID set, so it will not
be contained but will rather appear as a distinct entry in any returned
bundles. Both resources are added to a bundle, which will then have
two entries:
</p>
<macro name="snippet">
<param name="id" value="addIncludes" />
<param name="file" value="examples/src/main/java/example/IncludesExamples.java" />
</macro>
<p>
This will give the following output:
</p>
<source><![CDATA[<Bundle xmlns="http://hl7.org/fhir">
<id value="4e151274-2b19-4930-97f2-8427167a176c"/>
<type value="searchset"/>
<total value="1"/>
<link>
<relation value="fhir-base"/>
<url value="http://example.com/base"/>
</link>
<link>
<relation value="self"/>
<url value="http://example.com/base/Patient"/>
</link>
<entry>
<resource>
<Patient xmlns="http://hl7.org/fhir">
<id value="1333"/>
<identifier>
<system value="urn:mrns"/>
<value value="253345"/>
</identifier>
<managingOrganization>
<reference value="Organization/65546"/>
</managingOrganization>
</Patient>
</resource>
</entry>
<entry>
<resource>
<Organization xmlns="http://hl7.org/fhir">
<id value="65546"/>
<name value="Test Organization"/>
</Organization>
</resource>
<search>
<mode value="include"/>
</search>
</entry>
</Bundle>
]]></source>
</subsection>
<subsection name="Contained Resources">
<p>
On the other hand, if the linked resource
does not have an ID set, the linked resource will
be included in the returned bundle as a "contained" resource. In this
case, HAPI itself will define a local reference ID (e.g. "#1").
</p>
<source><![CDATA[// Create an organization, note that the organization does not have an ID
Organization org = new Organization();
org.getName().setValue("Contained Test Organization");
// Create a patient
Patient patient = new Patient();
patient.setId("Patient/1333");
patient.addIdentifier("urn:mrns", "253345");
// Put the organization as a reference in the patient resource
patient.getManagingOrganization().setResource(org);
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
System.out.println(encoded);]]></source>
<p>
This will give the following output:
</p>
<source><![CDATA[<Patient xmlns="http://hl7.org/fhir">
<contained>
<Organization xmlns="http://hl7.org/fhir" id="1">
<name value="Contained Test Organization"/>
</Organization>
</contained>
<identifier>
<system value="urn:mrns"/>
<value value="253345"/>
</identifier>
<managingOrganization>
<reference value="#1"/>
</managingOrganization>
</Patient>]]></source>
</subsection>
<p>
Note that you may also "contain" resources manually in your own code if you
prefer. The following example show how to do this:
</p>
<macro name="snippet">
<param name="id" value="manualContained" />
<param name="file" value="examples/src/main/java/example/ResourceRefs.java" />
</macro>
</section>
<section name="Versioned References">
<p>
By default, HAPI will strip resource versions from references between resources.
For example, if you set a reference to <code>Patient.managingOrganization</code>
to the value <code>Patient/123/_history/2</code>, HAPI will encode this
reference as <code>Patient/123</code>.
</p>
<p>
This is because in most circumstances, references between resources should be
versionless (e.g. the reference just points to the latest version, whatever
version that might be).
</p>
<p>
There are valid circumstances however for wanting versioned references. If you
need HAPI to emit versionned references, you have a few options:
</p>
<p>
You can force the parser to never strip versions:
</p>
<macro name="snippet">
<param name="id" value="disableStripVersions" />
<param name="file" value="examples/src/main/java/example/Parser.java" />
</macro>
<p>
You can also disable this behaviour entirely on the context (so that it
will apply to all parsers):
</p>
<macro name="snippet">
<param name="id" value="disableStripVersionsCtx" />
<param name="file" value="examples/src/main/java/example/Parser.java" />
</macro>
<p>
You can also configure HAPI to not strip versions only on certain fields. This
is desirable if you want versionless references in most places but need them
in some places:
</p>
<macro name="snippet">
<param name="id" value="disableStripVersionsField" />
<param name="file" value="examples/src/main/java/example/Parser.java" />
</macro>
</section>
</body>
</document>

View File

@ -2,6 +2,8 @@
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<!-- This content has been migrated -->
<properties>
<title>RESTful Client</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>

View File

@ -1,156 +1,158 @@
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<properties>
<title>Annotation Client</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<section name="The Annotation-Driven Client">
<p>
HAPI also provides a second style of client, called the <b>annotation-driven</b> client.
If you are using the
<a href="./doc_rest_client.html">Fluent/Generic Client</a>
do not need to read this page.
</p>
<p>
The design of the annotation-driven client
is intended to be similar to that of
JAX-WS, so users of that
specification should be comfortable with
this one. It uses a user-defined interface containing special
annotated methods which HAPI binds to calls against a server.
</p>
<p>
The annotation-driven client is particularly useful if you have a server that
exposes a set of specific operations (search parameter combinations, named queries, etc.)
and you want to let developers have a stongly/statically typed interface to that
server.
</p>
<p>
There is no difference in terms of capability between the two styles of
client. There is simply a difference in programming style and complexity. It
is probably safe to say that the generic client is easier to use and leads to
more readable code, at the expense of not giving any visibility into the
specific capabilities of the server you are interacting with.
</p>
<subsection name="Defining A Restful Client Interface">
<p>
The first step in creating an annotation-driven client is to define a
restful client interface.
</p>
<p>
A restful client interface class must extend the
<a href="./apidocs/ca/uhn/fhir/rest/client/api/IRestfulClient.html">IRestfulClient</a>
interface,
and will contain one or more methods which have been
annotated with special annotations indicating which RESTful
operation
that method supports. Below is a simple example of a
resource provider
which supports the
<a href="http://hl7.org/implement/standards/fhir/http.html#read">read</a>
operation (i.e. retrieve a single resource by ID) as well as the
<a href="http://hl7.org/implement/standards/fhir/http.html#search">search</a>
operation (i.e. find any resources matching a given criteria) for a
specific
search criteria.
</p>
<p>
You may notice that this interface looks a lot like the Resource
Provider
which is defined for use by the RESTful server. In fact, it
supports all
of the same annotations and is essentially identical,
other than the
fact that for a client you must use an interface but for a server you
must use a concrete class with method implementations.
</p>
<macro name="snippet">
<param name="id" value="provider" />
<param name="file"
value="examples/src/main/java/example/IRestfulClient.java" />
</macro>
<p>
You will probably want to add more methods
to your client interface.
See
<a href="./doc_rest_operations.html">RESTful Operations</a>
for
lots more examples of how to add methods for various operations.
</p>
</subsection>
<subsection name="Instantiate the Client">
<p>
Once your client interface is created, all that is left is to
create a FhirContext and instantiate the client and you are
ready to
start using it.
</p>
<macro name="snippet">
<param name="id" value="client" />
<param name="file"
value="examples/src/main/java/example/ExampleRestfulClient.java" />
</macro>
</subsection>
<subsection name="Configuring Encoding (JSON/XML)">
<p>
Restful client interfaces that you create will also extend
the interface
<a href="./apidocs/ca/uhn/fhir/rest/client/api/IRestfulClient.html">IRestfulClient</a>,
which comes with some helpful methods for configuring the way that
the client will interact with the server.
</p>
<p>
The following snippet shows how to configure the cliet to explicitly
request JSON or XML responses, and how to request "pretty printed" responses
on servers that support this (HAPI based servers currently).
</p>
<macro name="snippet">
<param name="id" value="clientConfig" />
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
</macro>
</subsection>
<subsection name="A Complete Example">
<p>
The following is a complete example showing a RESTful client
using
HAPI FHIR.
</p>
<macro name="snippet">
<param name="id" value="client" />
<param name="file"
value="examples/src/main/java/example/CompleteExampleClient.java" />
</macro>
</subsection>
</section>
</body>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<!-- This content has been migrated -->
<properties>
<title>Annotation Client</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<section name="The Annotation-Driven Client">
<p>
HAPI also provides a second style of client, called the <b>annotation-driven</b> client.
If you are using the
<a href="./doc_rest_client.html">Fluent/Generic Client</a>
do not need to read this page.
</p>
<p>
The design of the annotation-driven client
is intended to be similar to that of
JAX-WS, so users of that
specification should be comfortable with
this one. It uses a user-defined interface containing special
annotated methods which HAPI binds to calls against a server.
</p>
<p>
The annotation-driven client is particularly useful if you have a server that
exposes a set of specific operations (search parameter combinations, named queries, etc.)
and you want to let developers have a stongly/statically typed interface to that
server.
</p>
<p>
There is no difference in terms of capability between the two styles of
client. There is simply a difference in programming style and complexity. It
is probably safe to say that the generic client is easier to use and leads to
more readable code, at the expense of not giving any visibility into the
specific capabilities of the server you are interacting with.
</p>
<subsection name="Defining A Restful Client Interface">
<p>
The first step in creating an annotation-driven client is to define a
restful client interface.
</p>
<p>
A restful client interface class must extend the
<a href="./apidocs/ca/uhn/fhir/rest/client/api/IRestfulClient.html">IRestfulClient</a>
interface,
and will contain one or more methods which have been
annotated with special annotations indicating which RESTful
operation
that method supports. Below is a simple example of a
resource provider
which supports the
<a href="http://hl7.org/implement/standards/fhir/http.html#read">read</a>
operation (i.e. retrieve a single resource by ID) as well as the
<a href="http://hl7.org/implement/standards/fhir/http.html#search">search</a>
operation (i.e. find any resources matching a given criteria) for a
specific
search criteria.
</p>
<p>
You may notice that this interface looks a lot like the Resource
Provider
which is defined for use by the RESTful server. In fact, it
supports all
of the same annotations and is essentially identical,
other than the
fact that for a client you must use an interface but for a server you
must use a concrete class with method implementations.
</p>
<macro name="snippet">
<param name="id" value="provider" />
<param name="file"
value="examples/src/main/java/example/IRestfulClient.java" />
</macro>
<p>
You will probably want to add more methods
to your client interface.
See
<a href="./doc_rest_operations.html">RESTful Operations</a>
for
lots more examples of how to add methods for various operations.
</p>
</subsection>
<subsection name="Instantiate the Client">
<p>
Once your client interface is created, all that is left is to
create a FhirContext and instantiate the client and you are
ready to
start using it.
</p>
<macro name="snippet">
<param name="id" value="client" />
<param name="file"
value="examples/src/main/java/example/ExampleRestfulClient.java" />
</macro>
</subsection>
<subsection name="Configuring Encoding (JSON/XML)">
<p>
Restful client interfaces that you create will also extend
the interface
<a href="./apidocs/ca/uhn/fhir/rest/client/api/IRestfulClient.html">IRestfulClient</a>,
which comes with some helpful methods for configuring the way that
the client will interact with the server.
</p>
<p>
The following snippet shows how to configure the cliet to explicitly
request JSON or XML responses, and how to request "pretty printed" responses
on servers that support this (HAPI based servers currently).
</p>
<macro name="snippet">
<param name="id" value="clientConfig" />
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
</macro>
</subsection>
<subsection name="A Complete Example">
<p>
The following is a complete example showing a RESTful client
using
HAPI FHIR.
</p>
<macro name="snippet">
<param name="id" value="client" />
<param name="file"
value="examples/src/main/java/example/CompleteExampleClient.java" />
</macro>
</subsection>
</section>
</body>
</document>

View File

@ -1,136 +1,138 @@
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<properties>
<title>RESTful Client Examples</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<section name="Client Examples">
<p>
This page contains examples of how to use the client to perform
complete tasks. If you have an example you could contribute, we'd
love to hear from you!
</p>
<subsection name="Transaction With Placeholder IDs">
<p>
The following example shows how to post a transaction with two resources,
where one resource contains a reference to the other. A temporary ID (a UUID)
is used as an ID to refer to, and this ID will be replaced by the server by
a permanent ID.
</p>
<macro name="snippet">
<param name="id" value="conditional" />
<param name="file" value="examples/src/main/java/example/ClientTransactionExamples.java" />
</macro>
<p>
This code creates the following transaction bundle:<br/>
<source><![CDATA[<Bundle xmlns="http://hl7.org/fhir">
<type value="transaction"/>
<entry>
<fullUrl value="urn:uuid:47709cc7-b3ec-4abc-9d26-3df3d3d57907"/>
<resource>
<Patient xmlns="http://hl7.org/fhir">
<identifier>
<system value="http://acme.org/mrns"/>
<value value="12345"/>
</identifier>
<name>
<family value="Jameson"/>
<given value="J"/>
<given value="Jonah"/>
</name>
<gender value="male"/>
</Patient>
</resource>
<request>
<method value="POST"/>
<url value="Patient"/>
<ifNoneExist value="identifier=http://acme.org/mrns|12345"/>
</request>
</entry>
<entry>
<resource>
<Observation xmlns="http://hl7.org/fhir">
<status value="final"/>
<code>
<coding>
<system value="http://loinc.org"/>
<code value="789-8"/>
<display value="Erythrocytes [#/volume] in Blood by Automated count"/>
</coding>
</code>
<subject>
<reference value="urn:uuid:47709cc7-b3ec-4abc-9d26-3df3d3d57907"/>
</subject>
<valueQuantity>
<value value="4.12"/>
<unit value="10 trillion/L"/>
<system value="http://unitsofmeasure.org"/>
<code value="10*12/L"/>
</valueQuantity>
</Observation>
</resource>
<request>
<method value="POST"/>
<url value="Observation"/>
</request>
</entry>
</Bundle>]]></source>
</p>
<p>
The server responds with the following response. Note that
the ID of the already existing patient is returned, and the
ID of the newly created Observation is too.<br/>
<source><![CDATA[<Bundle xmlns="http://hl7.org/fhir">
<id value="dd1f75b8-e472-481e-97b3-c5eebb99a5e0"/>
<type value="transaction-response"/>
<link>
<relation value="self"/>
<url value="http://fhirtest.uhn.ca/baseDstu2"/>
</link>
<entry>
<response>
<status value="200 OK"/>
<location value="Patient/966810/_history/1"/>
<etag value="1"/>
<lastModified value="2015-10-29T07:25:42.465-04:00"/>
</response>
</entry>
<entry>
<response>
<status value="201 Created"/>
<location value="Observation/966828/_history/1"/>
<etag value="1"/>
<lastModified value="2015-10-29T07:33:28.047-04:00"/>
</response>
</entry>
</Bundle>]]></source>
</p>
</subsection>
<subsection name="Fetch all Pages of a Bundle">
<p>
<a href="https://github.com/jamesagnew/hapi-fhir/blob/master/examples/src/main/java/example/BundleFetcher.java">This example</a>
shows how to load all pages of a bundle by fetching each page one-after-the-other and then
joining the resuts.
</p>
</subsection>
</section>
</body>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<properties>
<title>RESTful Client Examples</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<!-- This content has been migrated -->
<body>
<section name="Client Examples">
<p>
This page contains examples of how to use the client to perform
complete tasks. If you have an example you could contribute, we'd
love to hear from you!
</p>
<subsection name="Transaction With Placeholder IDs">
<p>
The following example shows how to post a transaction with two resources,
where one resource contains a reference to the other. A temporary ID (a UUID)
is used as an ID to refer to, and this ID will be replaced by the server by
a permanent ID.
</p>
<macro name="snippet">
<param name="id" value="conditional" />
<param name="file" value="examples/src/main/java/example/ClientTransactionExamples.java" />
</macro>
<p>
This code creates the following transaction bundle:<br/>
<source><![CDATA[<Bundle xmlns="http://hl7.org/fhir">
<type value="transaction"/>
<entry>
<fullUrl value="urn:uuid:47709cc7-b3ec-4abc-9d26-3df3d3d57907"/>
<resource>
<Patient xmlns="http://hl7.org/fhir">
<identifier>
<system value="http://acme.org/mrns"/>
<value value="12345"/>
</identifier>
<name>
<family value="Jameson"/>
<given value="J"/>
<given value="Jonah"/>
</name>
<gender value="male"/>
</Patient>
</resource>
<request>
<method value="POST"/>
<url value="Patient"/>
<ifNoneExist value="identifier=http://acme.org/mrns|12345"/>
</request>
</entry>
<entry>
<resource>
<Observation xmlns="http://hl7.org/fhir">
<status value="final"/>
<code>
<coding>
<system value="http://loinc.org"/>
<code value="789-8"/>
<display value="Erythrocytes [#/volume] in Blood by Automated count"/>
</coding>
</code>
<subject>
<reference value="urn:uuid:47709cc7-b3ec-4abc-9d26-3df3d3d57907"/>
</subject>
<valueQuantity>
<value value="4.12"/>
<unit value="10 trillion/L"/>
<system value="http://unitsofmeasure.org"/>
<code value="10*12/L"/>
</valueQuantity>
</Observation>
</resource>
<request>
<method value="POST"/>
<url value="Observation"/>
</request>
</entry>
</Bundle>]]></source>
</p>
<p>
The server responds with the following response. Note that
the ID of the already existing patient is returned, and the
ID of the newly created Observation is too.<br/>
<source><![CDATA[<Bundle xmlns="http://hl7.org/fhir">
<id value="dd1f75b8-e472-481e-97b3-c5eebb99a5e0"/>
<type value="transaction-response"/>
<link>
<relation value="self"/>
<url value="http://fhirtest.uhn.ca/baseDstu2"/>
</link>
<entry>
<response>
<status value="200 OK"/>
<location value="Patient/966810/_history/1"/>
<etag value="1"/>
<lastModified value="2015-10-29T07:25:42.465-04:00"/>
</response>
</entry>
<entry>
<response>
<status value="201 Created"/>
<location value="Observation/966828/_history/1"/>
<etag value="1"/>
<lastModified value="2015-10-29T07:33:28.047-04:00"/>
</response>
</entry>
</Bundle>]]></source>
</p>
</subsection>
<subsection name="Fetch all Pages of a Bundle">
<p>
<a href="https://github.com/jamesagnew/hapi-fhir/blob/master/examples/src/main/java/example/BundleFetcher.java">This example</a>
shows how to load all pages of a bundle by fetching each page one-after-the-other and then
joining the resuts.
</p>
</subsection>
</section>
</body>
</document>

View File

@ -1,190 +1,192 @@
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<properties>
<title>Client Configuration</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<section name="Configuring Client Behaviour">
<p>
This page outlines ways that the client can be configured
for specific behaviour.
</p>
</section>
<a name="performance"/>
<section name="Performance">
<subsection name="Server Conformance Check">
<p>
By default, the client will query the server before the very first
operation to download the server's conformance/metadata statement
and verify that the server is appropriate for the given client.
This check is only done once per server endpoint for a given
FhirContext.
</p>
<p>
This check is useful to prevent bugs or unexpected behaviour
when talking to servers. It may introduce unneccesary overhead
however in circumstances where the client and server are known
to be compatible. The following example shows how to disable this
check.
</p>
<macro name="snippet">
<param name="id" value="dontValidate" />
<param name="file" value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
</subsection>
<subsection name="Deferred Model Scanning">
<p>
By default, HAPI will scan each model type it encounters
as soon as it encounters it. This scan includes a check for
all fields within the type, and makes use of reflection to do this.
</p>
<p>
While this process is not particularly significant on reasonably
performant machines (one benchmark showed that this takes
roughly 0.6 seconds to scan all types on one developer workstation), on some devices
(e.g. Android phones where every millisecond counts)
it may be desirable to defer this scan.
</p>
<p>
When the scan is deferred, objects will only be scanned when they
are actually accessed, meaning that only types that are
actually used in an application get scanned.
</p>
<p>
The following example shows how to defer model scanning:
</p>
<macro name="snippet">
<param name="id" value="deferModelScanning" />
<param name="file" value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
</subsection>
</section>
<section name="Configuring the HTTP Client">
<p>
RESTful clients (both Generic and Annotation-Driven) use
<a href="http://hc.apache.org/httpcomponents-client-ga/">Apache HTTP Client</a>
as a provider by default (except on Android, where
<a href="http://square.github.io/okhttp/">OkHttp</a>
is the default).
</p>
<p>
The Apache HTTP Client is very powerful and extremely
flexible,
but can be confusing at first to configure, because of the low-level
approach that
the library uses.
</p>
<p>
In many cases, the default configuration should suffice. HAPI FHIR
also encapsulates some of the more common configuration settings you
might want to use (socket timesouts, proxy settings, etc.) so that these
can be configured through HAPI's API without needing to understand the
underlying HTTP Client library.
</p>
<p>
This configuration is provided by accessing the
<a href="./apidocs/ca/uhn/fhir/rest/client/IRestfulClientFactory.html">IRestfulClientFactory</a>
class from the FhirContext.
</p>
<p>
Note that individual requests and responses
can be tweaked using
<a href="./doc_rest_client_interceptor.html">Client Interceptors.</a>
This approach is generally useful for configuration involving
tweaking the HTTP request/response, such as adding authorization headers
or logging.
</p>
<subsection name="Setting Socket Timeouts">
<p>
The following example shows how to configure low level
socket timeouts for client operations.
</p>
<macro name="snippet">
<param name="id" value="timeouts"/>
<param name="file"
value="examples/src/main/java/example/ClientExamples.java"/>
</macro>
</subsection>
<subsection name="Configuring an HTTP Proxy">
<p>
The following example shows how to configure the use of an HTTP
proxy in the client.
</p>
<macro name="snippet">
<param name="id" value="proxy"/>
<param name="file"
value="examples/src/main/java/example/ClientExamples.java"/>
</macro>
</subsection>
<subsection name="Using OkHttp instead of Apache HttpClient">
<p>
As of HAPI FHIR 2.0, an alternate client implementation
is available. This client replaces the low-level
Apache HttpClient implementation with the
Square
<a href="http://square.github.io/okhttp/">OkHttp</a>
library.
</p>
<p>
Changing HTTP implementations should be mostly
transparent (it has no effect on the actual FHIR
semantics which are transmitted over the wire) but
might be useful if you have an application that
uses OkHttp in other parts of the application and
has specific configuration for that library.
</p>
<p>
Note that as of HAPI FHIR 2.1, OkHttp is the default
provider on Android, and will be used without any
configuration being required. This is done because
HttpClient is deprecated on Android and has caused
problems in the past.
</p>
<p>
To use OkHttp, first add the library as a dependency to your project POM:
</p>
<source><![CDATA[<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-client-okhttp</artifactId>
<version>${hapi_stable_version}</version>
</dependency>]]></source>
<p>
Then, set the client factory to use OkHttp.
</p>
<macro name="snippet">
<param name="id" value="okhttp"/>
<param name="file"
value="examples/src/main/java/example/ClientExamples.java"/>
</macro>
</subsection>
</section>
</body>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<!-- Content has been migrated -->
<properties>
<title>Client Configuration</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<section name="Configuring Client Behaviour">
<p>
This page outlines ways that the client can be configured
for specific behaviour.
</p>
</section>
<a name="performance"/>
<section name="Performance">
<subsection name="Server Conformance Check">
<p>
By default, the client will query the server before the very first
operation to download the server's conformance/metadata statement
and verify that the server is appropriate for the given client.
This check is only done once per server endpoint for a given
FhirContext.
</p>
<p>
This check is useful to prevent bugs or unexpected behaviour
when talking to servers. It may introduce unneccesary overhead
however in circumstances where the client and server are known
to be compatible. The following example shows how to disable this
check.
</p>
<macro name="snippet">
<param name="id" value="dontValidate" />
<param name="file" value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
</subsection>
<subsection name="Deferred Model Scanning">
<p>
By default, HAPI will scan each model type it encounters
as soon as it encounters it. This scan includes a check for
all fields within the type, and makes use of reflection to do this.
</p>
<p>
While this process is not particularly significant on reasonably
performant machines (one benchmark showed that this takes
roughly 0.6 seconds to scan all types on one developer workstation), on some devices
(e.g. Android phones where every millisecond counts)
it may be desirable to defer this scan.
</p>
<p>
When the scan is deferred, objects will only be scanned when they
are actually accessed, meaning that only types that are
actually used in an application get scanned.
</p>
<p>
The following example shows how to defer model scanning:
</p>
<macro name="snippet">
<param name="id" value="deferModelScanning" />
<param name="file" value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
</subsection>
</section>
<section name="Configuring the HTTP Client">
<p>
RESTful clients (both Generic and Annotation-Driven) use
<a href="http://hc.apache.org/httpcomponents-client-ga/">Apache HTTP Client</a>
as a provider by default (except on Android, where
<a href="http://square.github.io/okhttp/">OkHttp</a>
is the default).
</p>
<p>
The Apache HTTP Client is very powerful and extremely
flexible,
but can be confusing at first to configure, because of the low-level
approach that
the library uses.
</p>
<p>
In many cases, the default configuration should suffice. HAPI FHIR
also encapsulates some of the more common configuration settings you
might want to use (socket timesouts, proxy settings, etc.) so that these
can be configured through HAPI's API without needing to understand the
underlying HTTP Client library.
</p>
<p>
This configuration is provided by accessing the
<a href="./apidocs/ca/uhn/fhir/rest/client/IRestfulClientFactory.html">IRestfulClientFactory</a>
class from the FhirContext.
</p>
<p>
Note that individual requests and responses
can be tweaked using
<a href="./doc_rest_client_interceptor.html">Client Interceptors.</a>
This approach is generally useful for configuration involving
tweaking the HTTP request/response, such as adding authorization headers
or logging.
</p>
<subsection name="Setting Socket Timeouts">
<p>
The following example shows how to configure low level
socket timeouts for client operations.
</p>
<macro name="snippet">
<param name="id" value="timeouts"/>
<param name="file"
value="examples/src/main/java/example/ClientExamples.java"/>
</macro>
</subsection>
<subsection name="Configuring an HTTP Proxy">
<p>
The following example shows how to configure the use of an HTTP
proxy in the client.
</p>
<macro name="snippet">
<param name="id" value="proxy"/>
<param name="file"
value="examples/src/main/java/example/ClientExamples.java"/>
</macro>
</subsection>
<subsection name="Using OkHttp instead of Apache HttpClient">
<p>
As of HAPI FHIR 2.0, an alternate client implementation
is available. This client replaces the low-level
Apache HttpClient implementation with the
Square
<a href="http://square.github.io/okhttp/">OkHttp</a>
library.
</p>
<p>
Changing HTTP implementations should be mostly
transparent (it has no effect on the actual FHIR
semantics which are transmitted over the wire) but
might be useful if you have an application that
uses OkHttp in other parts of the application and
has specific configuration for that library.
</p>
<p>
Note that as of HAPI FHIR 2.1, OkHttp is the default
provider on Android, and will be used without any
configuration being required. This is done because
HttpClient is deprecated on Android and has caused
problems in the past.
</p>
<p>
To use OkHttp, first add the library as a dependency to your project POM:
</p>
<source><![CDATA[<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-client-okhttp</artifactId>
<version>${hapi_stable_version}</version>
</dependency>]]></source>
<p>
Then, set the client factory to use OkHttp.
</p>
<macro name="snippet">
<param name="id" value="okhttp"/>
<param name="file"
value="examples/src/main/java/example/ClientExamples.java"/>
</macro>
</subsection>
</section>
</body>
</document>

View File

@ -21,60 +21,7 @@
</section>
<section name="Client Side ETags">
<p>
ETag features are added simply by adding fluent method calls to the
client method chain, as shown in the following examples.
</p>
<a name="client_read"/>
<subsection name="Read / VRead">
<p>
To notify the server that it should return an <code>HTTP 304 Not Modified</code>
if the content has not changed, add an <code>ifVersionMatches(foo).[operation]</code>
invocation.
</p>
<macro name="snippet">
<param name="id" value="etagread" />
<param name="file" value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
<p>
This method will add the following header to the request:
</p>
<source>If-None-Match: "001"</source>
</subsection>
<a name="client_update"/>
<subsection name="Update">
<p>
To implement version aware updates, specify a version in the
request. This will notify the server that it should only update the
resource on the server if the version matches the given version. This
is useful to prevent two clients from attempting to modify the
resource at the same time, and having one client's updates overwrite
the other's.
</p>
<macro name="snippet">
<param name="id" value="etagupdate" />
<param name="file" value="examples/src/main/java/example/GenericClientExample.java" />
</macro>
<p>
The following header will be added to the request as a part of this
interaction.
</p>
<source>If-Match: "001"</source>
</subsection>
</section>
<section name="Server Side ETags">

View File

@ -1090,7 +1090,7 @@ If-Match: W/"3"]]></pre>
<p>
It is also possible to annotate search methods and/or parameters with
the
<a href="./apidocs/ca/uhn/fhir/model/api/annotation/Description.html">@Description</a>
<a href="/hapi-fhir/apidocs/ca/uhn/fhir/model/api/annotation/Description.html">@Description</a>
annotation. This annotation allows you to add a description of the method
and the individual parameters. These descriptions will be placed in the
server's conformance statement, which can be helpful to anyone who is developing

View File

@ -1,89 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<properties>
<title>JAX-RS Server</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<section name="JAX-RS Server">
<p>
The standard server is implemented using Servlet technology. A <a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jaxrsserver-base">module</a>
exists which implements the server using <a href="https://jax-rs-spec.java.net/nonav/2.0/apidocs/index.html">JAX-RS</a> 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
<a href="./doc_rest_server.html#ConformanceMetadata_Statement">Conformance Statements</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Read.html">@Read</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Search.html">@Search</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Create.html">@Create</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Update.html">@Update</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Delete.html">@Delete</a> and
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Operation.html">@Operation</a>.
</p>
<p>
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 <a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jaxrsserver-example">here</a>.
</p>
<subsection name="JAX-RS Implementation specifics">
<p>
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 <a href="./doc_rest_operations.html">annotation</a> on the methods in the <a href="#Defining_Resource_Providers">Resource Providers</a> in order to be able to call them.
</p>
<p>
Implementing a JAX-RS Resource Provider requires some JAX-RS annotations. The <code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/Path.html">@Path</a></code>
annotation needs to define the resource path. The <code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/Produces.html">@Produces</a></code> 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
<code><a href="http://jamesagnew.github.io/hapi-fhir/apidocs/ca/uhn/fhir/jaxrs/server/AbstractJaxRsResourceProvider.html">AbstractJaxRsResourceProvider</a></code>.
<macro name="snippet">
<param name="id" value="jax-rs-provider-construction" />
<param name="file" value="examples/src/main/java/example/JaxRsPatientRestProvider.java" />
</macro>
</p>
<p>
<a href="./doc_rest_operations.html#Extended_Operations">Extended Operations</a> require the correct JAX-RS (
<code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/Path.html">@Path</a></code>,
<code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/GET.html">@GET</a></code> or
<code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/POST.html">@POST</a></code>) annotations. The body of the method needs to call the
method <code><a href="http://jamesagnew.github.io/hapi-fhir/apidocs/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">AbstractJaxRsResourceProvider#customOperation</a></code>
with the correct parameters. The server will then call the method with corresponding name.
<macro name="snippet">
<param name="id" value="jax-rs-provider-operation" />
<param name="file" value="examples/src/main/java/example/JaxRsPatientRestProvider.java" />
</macro>
</p>
<p>
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 <code><a href="http://jamesagnew.github.io/hapi-fhir/apidocs/ca/uhn/fhir/jaxrs/server/AbstractJaxRsResourceProvider.html#getProviders">AbstractJaxRsResourceProvider#getProviders</a></code>.
This method is called once, during <code><a href="https://docs.oracle.com/javaee/6/api/javax/annotation/PostConstruct.html">PostConstruct</a></code>.
<macro name="snippet">
<param name="id" value="jax-rs-conformance" />
<param name="file" value="examples/src/main/java/example/JaxRsConformanceProvider.java" />
</macro>
</p>
</subsection>
</section>
<section name="A Complete Example">
<p>
A complete example showing how to implement a JAX-RS RESTful server can
be found in our Git repo here:
<a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jaxrsserver-example">https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jaxrsserver-example</a>
</p>
</section>
</body>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<!-- This content has been migrated -->
<properties>
<title>JAX-RS Server</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<section name="JAX-RS Server">
<p>
The standard server is implemented using Servlet technology. A <a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jaxrsserver-base">module</a>
exists which implements the server using <a href="https://jax-rs-spec.java.net/nonav/2.0/apidocs/index.html">JAX-RS</a> 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
<a href="./doc_rest_server.html#ConformanceMetadata_Statement">Conformance Statements</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Read.html">@Read</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Search.html">@Search</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Create.html">@Create</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Update.html">@Update</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Delete.html">@Delete</a> and
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Operation.html">@Operation</a>.
</p>
<p>
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 <a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jaxrsserver-example">here</a>.
</p>
<subsection name="JAX-RS Implementation specifics">
<p>
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 <a href="./doc_rest_operations.html">annotation</a> on the methods in the <a href="#Defining_Resource_Providers">Resource Providers</a> in order to be able to call them.
</p>
<p>
Implementing a JAX-RS Resource Provider requires some JAX-RS annotations. The <code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/Path.html">@Path</a></code>
annotation needs to define the resource path. The <code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/Produces.html">@Produces</a></code> 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
<code><a href="http://jamesagnew.github.io/hapi-fhir/apidocs/ca/uhn/fhir/jaxrs/server/AbstractJaxRsResourceProvider.html">AbstractJaxRsResourceProvider</a></code>.
<macro name="snippet">
<param name="id" value="jax-rs-provider-construction" />
<param name="file" value="examples/src/main/java/example/JaxRsPatientRestProvider.java" />
</macro>
</p>
<p>
<a href="./doc_rest_operations.html#Extended_Operations">Extended Operations</a> require the correct JAX-RS (
<code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/Path.html">@Path</a></code>,
<code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/GET.html">@GET</a></code> or
<code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/POST.html">@POST</a></code>) annotations. The body of the method needs to call the
method <code><a href="http://jamesagnew.github.io/hapi-fhir/apidocs/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">AbstractJaxRsResourceProvider#customOperation</a></code>
with the correct parameters. The server will then call the method with corresponding name.
<macro name="snippet">
<param name="id" value="jax-rs-provider-operation" />
<param name="file" value="examples/src/main/java/example/JaxRsPatientRestProvider.java" />
</macro>
</p>
<p>
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 <code><a href="http://jamesagnew.github.io/hapi-fhir/apidocs/ca/uhn/fhir/jaxrs/server/AbstractJaxRsResourceProvider.html#getProviders">AbstractJaxRsResourceProvider#getProviders</a></code>.
This method is called once, during <code><a href="https://docs.oracle.com/javaee/6/api/javax/annotation/PostConstruct.html">PostConstruct</a></code>.
<macro name="snippet">
<param name="id" value="jax-rs-conformance" />
<param name="file" value="examples/src/main/java/example/JaxRsConformanceProvider.java" />
</macro>
</p>
</subsection>
</section>
<section name="A Complete Example">
<p>
A complete example showing how to implement a JAX-RS RESTful server can
be found in our Git repo here:
<a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jaxrsserver-example">https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jaxrsserver-example</a>
</p>
</section>
</body>
</document>

View File

@ -315,7 +315,7 @@
<p>
HAPI FHIR 3.7.0 introduced a new interceptor, the
<a href="./apidocs/ca/uhn/fhir/rest/server/interceptor/auth/SearchNarrowingInterceptor.html">SearchNarrowingInterceptor</a>.
<a href="./apidocs/hapi-fhir-server/ca/uhn/fhir/rest/server/interceptor/auth/SearchNarrowingInterceptor.html">SearchNarrowingInterceptor</a>.
</p>
<p>
This interceptor is designed to be used in conjunction with AuthorizationInterceptor. It

View File

@ -1,203 +1,205 @@
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<properties>
<title>Server Tester</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<section name="FHIR Tester Web Application">
<macro name="toc">
</macro>
<p>
HAPI FHIR includes a web UI that can be used to test your server implementation.
This UI is the same UI used on the <a href="http://fhirtest.uhn.ca">http://fhirtest.uhn.ca</a>
public server.
</p>
<p>
The Tester is a
<a href="http://maven.apache.org/plugins/maven-war-plugin/overlays.html">Maven WAR Overlay</a>,
meaning that you create your own WAR project (which you would likely be doing anyway
to create your server) and the overlay drops a number of files into your project.
</p>
<subsection name="Adding the Overlay">
<p>
These instructions assume that you have an exsiting web project
which uses Maven to build. The POM.xml should have a "packaging"
type of "war".
</p>
<p>
Adding the overlay to your project is relatively simple. First,
add the "hapi-fhir-testpage-overlay" dependency to the dependencies
section of your POM.xml file.
<source><![CDATA[<dependencies>
<!-- ... other dependencies ... -->
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-testpage-overlay</artifactId>
<version>${project.version}</version>
<type>war</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-testpage-overlay</artifactId>
<version>${project.version}</version>
<classifier>classes</classifier>
<scope>provided</scope>
</dependency>
</dependencies>]]></source>
</p>
<p>
Then, add the following WAR plugin to the plugins section
of your POM.xml
<source><![CDATA[<build>
<plugins>
<!-- ... other plugins ... -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<overlays>
<overlay>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-testpage-overlay</artifactId>
</overlay>
</overlays>
</configuration>
</plugin>
</plugins>
</build>]]></source>
</p>
<p>
Then, create a Java source file
called <code>FhirTesterConfig.java</code>
and copy in the following contents:
</p>
<macro name="snippet">
<param name="file" value="restful-server-example/src/main/java/ca/uhn/example/config/FhirTesterConfig.java" />
</macro>
<p>
Note that the URL in the file above must be customized to point to
the FHIR endpoint your server will be deployed to. For example, if you
are naming your project "myfhir-1.0.war" and your endpoint in the WAR is
deployed to "/fhirbase/*" then you should put a URL similar to
<code>http://localhost:8080/myfhir-1.0/fhirbase</code>
</p>
<p>
Next, create the following directory in your project
if it doesn't already exist:<br/>
<code>src/main/webapp/WEB-INF</code>
</p>
<p>
In this directory you should open your <code>web.xml</code> file, or create
it if it doesn't exist.
This file is
required in order to deploy to a servlet container and you should create it if
it does not already exist. Place the following contents in that file, adjusting
the package on the <code>FhirTesterConfig</code> to match the
actual package in which you placed this file.
</p>
<source><![CDATA[<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>ca.uhn.example.config.FhirTesterConfig</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/tester/*</url-pattern>
</servlet-mapping>
]]></source>
</subsection>
<subsection name="Customizing the Overlay">
<p>
The most important customization required is to
set the FHIR server base URL in the
<code>hapi-fhir-tester-config.xml</code>
configuration file created during the
previous step.
</p>
<p>
Beyond this, the entire tester application is built
from a number of
<a href="http://thymeleaf.org">Thymeleaf</a>
template files, any of which can be replaced to
create your own look and feel. All of the templates
can be found in your built war (after running the Maven
build), or in the target directory's staging area, in
<code>WEB-INF/templates</code>. By placing a file
with the same path/name in your <code>src/main/webapp/WEB-INF/templates</code>
directory you can replace the built in template
with your own file.
</p>
</subsection>
<subsection name="A Complete Example">
<p>
The "Restful Server Example" project contains a complete working
example of the FHIR Tester as a part of its configuration. You may
wish to browse its source to see how this works:<br/>
<a href="https://github.com/jamesagnew/hapi-fhir/tree/master/restful-server-example">https://github.com/jamesagnew/hapi-fhir/tree/master/restful-server-example</a>
</p>
</subsection>
</section>
<section name="Authorization">
<p>
The testing UI uses its own client to talk to your FHIR server. In other words, there are no
special "hooks" which the tested uses to retrieve data from your server, it acts as an HTTP client
just like any other client.
</p>
<p>
This does mean that if your server has any authorization requirements, you will need to configure the
tester UI to meet those requirements. For example, if your server has been configured to require
a HTTP Basic Auth header (e.g. <code>Authorization: Basic VVNFUjpQQVNT</code>) you need to
configure the tester UI to send those credentials across when it is acting as
a FHIR client.
</p>
<p>
This is done by providing your own implementation of the <code>ITestingUiClientFactory</code>
interface. This interface takes in some details about the incoming request and produces
a client.
</p>
</section>
</body>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<!-- This content is migrated -->
<properties>
<title>Server Tester</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<section name="FHIR Tester Web Application">
<macro name="toc">
</macro>
<p>
HAPI FHIR includes a web UI that can be used to test your server implementation.
This UI is the same UI used on the <a href="http://fhirtest.uhn.ca">http://fhirtest.uhn.ca</a>
public server.
</p>
<p>
The Tester is a
<a href="http://maven.apache.org/plugins/maven-war-plugin/overlays.html">Maven WAR Overlay</a>,
meaning that you create your own WAR project (which you would likely be doing anyway
to create your server) and the overlay drops a number of files into your project.
</p>
<subsection name="Adding the Overlay">
<p>
These instructions assume that you have an exsiting web project
which uses Maven to build. The POM.xml should have a "packaging"
type of "war".
</p>
<p>
Adding the overlay to your project is relatively simple. First,
add the "hapi-fhir-testpage-overlay" dependency to the dependencies
section of your POM.xml file.
<source><![CDATA[<dependencies>
<!-- ... other dependencies ... -->
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-testpage-overlay</artifactId>
<version>${project.version}</version>
<type>war</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-testpage-overlay</artifactId>
<version>${project.version}</version>
<classifier>classes</classifier>
<scope>provided</scope>
</dependency>
</dependencies>]]></source>
</p>
<p>
Then, add the following WAR plugin to the plugins section
of your POM.xml
<source><![CDATA[<build>
<plugins>
<!-- ... other plugins ... -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<overlays>
<overlay>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-testpage-overlay</artifactId>
</overlay>
</overlays>
</configuration>
</plugin>
</plugins>
</build>]]></source>
</p>
<p>
Then, create a Java source file
called <code>FhirTesterConfig.java</code>
and copy in the following contents:
</p>
<macro name="snippet">
<param name="file" value="restful-server-example/src/main/java/ca/uhn/example/config/FhirTesterConfig.java" />
</macro>
<p>
Note that the URL in the file above must be customized to point to
the FHIR endpoint your server will be deployed to. For example, if you
are naming your project "myfhir-1.0.war" and your endpoint in the WAR is
deployed to "/fhirbase/*" then you should put a URL similar to
<code>http://localhost:8080/myfhir-1.0/fhirbase</code>
</p>
<p>
Next, create the following directory in your project
if it doesn't already exist:<br/>
<code>src/main/webapp/WEB-INF</code>
</p>
<p>
In this directory you should open your <code>web.xml</code> file, or create
it if it doesn't exist.
This file is
required in order to deploy to a servlet container and you should create it if
it does not already exist. Place the following contents in that file, adjusting
the package on the <code>FhirTesterConfig</code> to match the
actual package in which you placed this file.
</p>
<source><![CDATA[<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>ca.uhn.example.config.FhirTesterConfig</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/tester/*</url-pattern>
</servlet-mapping>
]]></source>
</subsection>
<subsection name="Customizing the Overlay">
<p>
The most important customization required is to
set the FHIR server base URL in the
<code>hapi-fhir-tester-config.xml</code>
configuration file created during the
previous step.
</p>
<p>
Beyond this, the entire tester application is built
from a number of
<a href="http://thymeleaf.org">Thymeleaf</a>
template files, any of which can be replaced to
create your own look and feel. All of the templates
can be found in your built war (after running the Maven
build), or in the target directory's staging area, in
<code>WEB-INF/templates</code>. By placing a file
with the same path/name in your <code>src/main/webapp/WEB-INF/templates</code>
directory you can replace the built in template
with your own file.
</p>
</subsection>
<subsection name="A Complete Example">
<p>
The "Restful Server Example" project contains a complete working
example of the FHIR Tester as a part of its configuration. You may
wish to browse its source to see how this works:<br/>
<a href="https://github.com/jamesagnew/hapi-fhir/tree/master/restful-server-example">https://github.com/jamesagnew/hapi-fhir/tree/master/restful-server-example</a>
</p>
</subsection>
</section>
<section name="Authorization">
<p>
The testing UI uses its own client to talk to your FHIR server. In other words, there are no
special "hooks" which the tested uses to retrieve data from your server, it acts as an HTTP client
just like any other client.
</p>
<p>
This does mean that if your server has any authorization requirements, you will need to configure the
tester UI to meet those requirements. For example, if your server has been configured to require
a HTTP Basic Auth header (e.g. <code>Authorization: Basic VVNFUjpQQVNT</code>) you need to
configure the tester UI to send those credentials across when it is acting as
a FHIR client.
</p>
<p>
This is done by providing your own implementation of the <code>ITestingUiClientFactory</code>
interface. This interface takes in some details about the incoming request and produces
a client.
</p>
</section>
</body>
</document>

View File

@ -1,98 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<properties>
<title>Tinder</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<section name="Tinder">
<macro name="toc">
</macro>
<p>
According to the FHIR specification, any conformant server
must be able to export a Conformance statement, which
indicates all of the resource types and potential operations
that the server supports.
</p>
<p>
HAPI provides a Maven plugin called "Tinder" which is able to automatically
generate a client based on that conformance statement.
</p>
</section>
<section name="Client Generation">
<p>
The following example shows a simple Maven plugin which
builds a client for the Health Intersections reference
server.
</p>
<p>
Note that as of HAPI 0.8, you need to add a dependency to the
plugin containing the version of FHIR you are building custom
structures against.
</p>
<source><![CDATA[<plugins>
<plugin>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-tinder-plugin</artifactId>
<version>${project.version}</version>
<executions>
<execution>
<goals><goal>generate-structures</goal></goals>
<configuration>
<clientClassName>ca.uhn.hitest.HiTest</clientClassName>
<serverBaseHref>http://fhir.healthintersections.com.au/open</serverBaseHref>
<generateSearchForAllParams>true</generateSearchForAllParams>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>]]></source>
<p>
This example will create a class called
<code>ca.uhn.hitest.HiTest</code> which has
methods to invoke the various server operations.
</p>
<p>
It is then possible to use this client as simply as:
</p>
<source><![CDATA[// Instantiate the client
FhirContext ctx = new FhirContext(Patient.class);
IRestfulClientFactory clientFactory = ctx.newRestfulClientFactory();
ClientClass client = clientFactory.newClient(ClientClass.class, "http://fhir.healthintersections.com.au/open");
// Invoke the client
Bundle bundle = client.searchPatientByGender(new StringDt("M"));
System.out.println(bundle.getEntries().size());
// Prints: 50
Patient patientOne = (Patient) bundle.getEntries().get(0).getResource();
System.out.println(patientOne.getName().get(0).getFamily().get(0).getValue());
// Prints: Chalmers]]></source>
</section>
</body>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<properties>
<title>Tinder</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<!-- This content should not be migrated -->
<body>
<section name="Tinder">
<macro name="toc">
</macro>
<p>
According to the FHIR specification, any conformant server
must be able to export a Conformance statement, which
indicates all of the resource types and potential operations
that the server supports.
</p>
<p>
HAPI provides a Maven plugin called "Tinder" which is able to automatically
generate a client based on that conformance statement.
</p>
</section>
<section name="Client Generation">
<p>
The following example shows a simple Maven plugin which
builds a client for the Health Intersections reference
server.
</p>
<p>
Note that as of HAPI 0.8, you need to add a dependency to the
plugin containing the version of FHIR you are building custom
structures against.
</p>
<source><![CDATA[<plugins>
<plugin>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-tinder-plugin</artifactId>
<version>${project.version}</version>
<executions>
<execution>
<goals><goal>generate-structures</goal></goals>
<configuration>
<clientClassName>ca.uhn.hitest.HiTest</clientClassName>
<serverBaseHref>http://fhir.healthintersections.com.au/open</serverBaseHref>
<generateSearchForAllParams>true</generateSearchForAllParams>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>]]></source>
<p>
This example will create a class called
<code>ca.uhn.hitest.HiTest</code> which has
methods to invoke the various server operations.
</p>
<p>
It is then possible to use this client as simply as:
</p>
<source><![CDATA[// Instantiate the client
FhirContext ctx = new FhirContext(Patient.class);
IRestfulClientFactory clientFactory = ctx.newRestfulClientFactory();
ClientClass client = clientFactory.newClient(ClientClass.class, "http://fhir.healthintersections.com.au/open");
// Invoke the client
Bundle bundle = client.searchPatientByGender(new StringDt("M"));
System.out.println(bundle.getEntries().size());
// Prints: 50
Patient patientOne = (Patient) bundle.getEntries().get(0).getResource();
System.out.println(patientOne.getName().get(0).getFamily().get(0).getValue());
// Prints: Chalmers]]></source>
</section>
</body>
</document>

View File

@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<!-- This content has been mgrated -->
<properties>
<title>Validation</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>