Documentation updates

This commit is contained in:
James Agnew 2019-11-26 02:00:22 -03:00
parent 5becb613fe
commit 5f803f7e68
28 changed files with 1740 additions and 269 deletions

View File

@ -20,12 +20,12 @@ package ca.uhn.hapi.fhir.docs;
* #L%
*/
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
import ca.uhn.fhir.rest.server.IResourceProvider;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.Patient;
import java.util.ArrayList;
@ -36,14 +36,14 @@ public class ExampleProviders {
//START SNIPPET: plainProvider
public class PlainProvider {
public class MyPlainProvider {
/**
* This method is a Patient search, but HAPI can not automatically
* determine the resource type so it must be explicitly stated.
*/
@Search(type=Patient.class)
public Bundle searchForPatients(@RequiredParam(name=Patient.SP_NAME) StringDt theName) {
public Bundle searchForPatients(@RequiredParam(name=Patient.SP_NAME) StringType theName) {
Bundle retVal = new Bundle();
// perform search
return retVal;
@ -65,9 +65,7 @@ public class ExampleServlet extends ca.uhn.fhir.rest.server.RestfulServer {
* as resource providers. You may pass both resource providers
* and and plain providers to the same server if you like.
*/
List<Object> plainProviders=new ArrayList<Object>();
plainProviders.add(new PlainProvider());
registerProviders(plainProviders);
registerProvider(new MyPlainProvider());
List<IResourceProvider> resourceProviders = new ArrayList<IResourceProvider>();
// ...add some resource providers...

View File

@ -959,7 +959,7 @@ public interface HistoryClient extends IBasicClient {
public void bbbbb() throws DataFormatException, IOException {
//START SNIPPET: metadataClientUsage
FhirContext ctx = FhirContext.forDstu2();
FhirContext ctx = FhirContext.forR4();
MetadataClient client = ctx.newRestfulClient(MetadataClient.class, "http://spark.furore.com/fhir");
CapabilityStatement metadata = client.getServerMetadata();
System.out.println(ctx.newXmlParser().encodeResourceToString(metadata));
@ -995,7 +995,7 @@ private interface IPatientClient extends IBasicClient
public void clientRead() {
//START SNIPPET: clientReadTags
IPatientClient client = FhirContext.forDstu2().newRestfulClient(IPatientClient.class, "http://foo/fhir");
IPatientClient client = FhirContext.forR4().newRestfulClient(IPatientClient.class, "http://foo/fhir");
Patient patient = client.readPatient(new IdType("1234"));
// Access the tag list
@ -1050,7 +1050,6 @@ public Bundle transaction(@TransactionParam Bundle theInput) {
}
//END SNIPPET: transaction
}

View File

@ -15,7 +15,7 @@ The following is a list of key subprojects you might open in your IDE:
# Getting the Sources
<p style="float:right;">
<a class="externalLink" href="https://dev.azure.com/jamesagnew214/jamesagnew214/_build/latest?definitionId=1&branchName=master"><img src="https://dev.azure.com/jamesagnew214/jamesagnew214/_apis/build/status/jamesagnew.hapi-fhir?branchName=master" alt="Build Status" class="img-fluid"></a>
<a class="externalLink" href="https://dev.azure.com/jamesagnew214/jamesagnew214/_build/latest?definitionId=1&branchName=master"><img src="https://dev.azure.com/jamesagnew214/jamesagnew214/_apis/build/status/jamesagnew.hapi-fhir?branchName=master" alt="Build Status" class="img-fluid"/></a>
</p>
The best way to grab our sources is with Git. Grab the repository URL from our [GitHub page](https://github.com/jamesagnew/hapi-fhir). We try our best to ensure that the sources are always left in a buildable state. Check Azure Pipelines CI (see the image/link on the right) to see if the sources currently build.
@ -87,30 +87,11 @@ Next, browse to the directory where you checked out the HAPI FHIR sources. You m
<img src="../../images/hacking_import_step2.png"/>
##
<subsection name="Troubleshooting">
<p>
When importing the HAPI projects into Eclipse, sometimes Eclipse
will fail to correctly import libraries. If you import a module
into Eclipse and it fails to compile with many errors relating to
packages other than HAPI's, the following steps will fix this:
</p>
<ul>
<li>Delete the project from your Eclipse workspace</li>
<li>
On the local filesystem, delete the files <code>.project</code>
and <code>.classpath</code>, and the directory <code>.settings</code>
from each module you want to open.
</li>
<li>
Import each module again using the instructions above
</li>
</ul>
</subsection>
</section>
</body>
## Troubleshooting
When importing the HAPI projects into Eclipse, sometimes Eclipse will fail to correctly import libraries. If you import a module into Eclipse and it fails to compile with many errors relating to packages other than HAPI's, the following steps will fix this:
* Delete the project from your Eclipse workspace
* On the local filesystem, delete the files `.project` and `.classpath`, and the directory `.settings` from each module you want to open.
* Import each module again using the instructions above
</document>

View File

@ -13,15 +13,33 @@ page.model.converter=Version Converters
page.model.custom_structures=Custom Structures
page.model.narrative_generation=Narrative Generation
section.server.title=Plain Server
page.server.cors=CORS
section.server_plain.title=Plain Server
page.server_plain.server_types=REST Server Types
page.server_plain.introduction=Plain Server Introduction
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.paging=Paging Search Results
page.server_plain.cors=CORS
page.server_plain.multitenency=Multitenency
section.jpa.title=JPA Server
section.jpa.jpa_server=JPA Server
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
section.interceptors.title=Interceptors
page.interceptors.interceptors=Interceptors Overview
section.security.title=Security
page.security.introduction=Introduction
page.security.authorization_interceptor=Authorization Interceptor
page.security.consent_interceptor=Consent Interceptor
page.security.narrowing_interceptor=Narrowing Interceptor
section.validation.title=Validation
section.validation.examples=Validation Examples

View File

@ -1,221 +0,0 @@
# JPA Server
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.
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.
**Important Note:** This implementation uses a fairly simple table design, with a single table being used to hold resource bodies (which are stored as CLOBs, optionally GZipped to save space) and a set of tables to hold search indexes, tags, history details, etc. This design is only one of many possible ways
of designing a FHIR server so it is worth considering whether it is appropriate for the problem you are trying to solve.
# Getting Started
The recommended way to get started with HAPI's JPA server module is
to begin with the starter project. This project can be found at the following link: [https://github.com/hapifhir/hapi-fhir-jpaserver-starter](https://github.com/hapifhir/hapi-fhir-jpaserver-starter)
This project is a fully contained FHIR server, supporting all standard operations (read/create/delete/etc). It bundles an embedded instance of the <a href="http://h2database.com">H2 Java Database</a> so that the server can run without depending on any external database, but it can also be configured to use an installation of Oracle, Postgres, etc.
# Configuration Options
## External/Absolute Resource References
Clients may sometimes post resources to your server that contain absolute resource references. For example, consider the following resource:
```xml
<Patient xmlns="http://hl7.org/fhir">
<id value="patient-infant-01"/>
<name>
<use value="official"/>
<family value="Miller"/>
<given value="Samuel"/>
</name>
<managingOrganization>
<reference value="http://example.com/fhir/Organization/123"/>
</managingOrganization>
</Patient>
```
By default, the server will reject this reference, as only local references are permitted by the server. This can be changed however.
If you want the server to recognize that this URL is actually a local reference (i.e. because the server will be deployed to the base URL `http://example.com/fhir/`) you can configure the server to recognize this URL via the following DaoConfig setting:
```java
@Bean
public DaoConfig daoConfig() {
DaoConfig retVal = new DaoConfig();
// ... other config ...
retVal.getTreatBaseUrlsAsLocal().add("http://example.com/fhir/");
return retVal;
}
```
On the other hand, if you want the server to be configurable to allow remote references, you can set this with the confguration below. Using the `setAllowExternalReferences` means that it will be possible to search for references that refer to these external references.
```java
@Bean
public DaoConfig daoConfig() {
DaoConfig retVal = new DaoConfig();
// Allow external references
retVal.setAllowExternalReferences(true);
// If you are allowing external references, it is recommended to
// also tell the server which references actually will be local
retVal.getTreatBaseUrlsAsLocal().add("http://mydomain.com/fhir");
return retVal;
}
```
## Logical References
In some cases, you may have references which are <i>Logical References</i>,
which means that they act as an identifier and not necessarily as a literal
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 neccesarily 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-)).
For example:
```java
// Treat specific URL as logical
myDaoConfig.getTreatReferencesAsLogical().add("http://mysystem.com/ValueSet/cats-and-dogs");
// Treat all references with given prefix as logical
myDaoConfig.getTreatReferencesAsLogical().add("http://mysystem.com/mysystem-vs-*");
```
# Search Result Caching
By default, search results will be cached for one minute. This means that if a client performs a search for <code>Patient?name=smith</code> and gets back 500 results, if a client performs the same search within 60000 milliseconds the previously loaded search results will be returned again. This also means that any new Patient resources named "Smith" within the last minute will not be reflected in the results.
Under many normal scenarios this is a n acceptable performance tradeoff, but in some cases it is not. If you want to disable caching, you have two options:
### Globally Disable / Change Caching Timeout
You can change the global cache using the following setting:
```java
myDaoConfig.setReuseCachedSearchResultsForMillis(null);
```
### Disable Cache at the Request Level
Clients can selectively disable caching for an individual request using the Cache-Control header:
```http
Cache-Control: no-cache
```
### Disable Paging at the Request Level
If the client knows that they will only want a small number of results (for example, a UI containing 20 results is being shown and the client knows that they will never load the next page of results) the client
may also use the <code>no-store</code> directive along with a HAPI FHIR extension called <code>max-results</code> in order to specify that only the given number of results should be fetched. This directive disabled paging entirely for the request and causes the request to return immediately when the given number of results is found. This can cause a noticeable performance improvement in some cases.
```http
Cache-Control: no-store, max-results=20
```
# Architecture
<img src="/hapi-fhir/docs/images/jpa_architecture.png" alt="Architecture" align="right"/>
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.
The resource providers also extend a superclass which implements all of the other FHIR methods, such as Read, Create, Delete, etc.
Note that these resource providers are generated as a part of the HAPI build process, so they are not checked into Git. The resource providers do not actually implement any of the logic in searching, updating, etc. They simply receive the incoming HTTP calls (via the RestfulServer) and pass along the incoming requests to the DAOs.
* **HAPI DAOs:** The DAOs actually implement all of the database business logic relating to the storage, indexing, and retrieval of FHIR resources, using the underlying JPA API.
* **Hibernate:** The HAPI JPA Server uses the JPA library, implemented by Hibernate. No Hibernate specific features are used, so the library should also work with other providers (e.g. Eclipselink) but it is not tested regularly with them.
* **Database:** The RESTful server uses an embedded Derby database, but can be configured to talk to [any database supported by Hibernate](https://developer.jboss.org/wiki/SupportedDatabases2?_sscc=t).
# Additional Information
* [This page](https://www.openhealthhub.org/t/hapi-terminology-server-uk-snomed-ct-import/592) has information on loading national editions (UK specifically) of SNOMED CT files into the database.
<a name="upgrading"/>
# Upgrading HAPI FHIR JPA
HAPI FHIR JPA is a constantly evolving product, with new features being added to each new version of the library. As a result, it is generally necessary to execute a database migration as a part of an upgrade to HAPI FHIR.
When upgrading the JPA server from one version of HAPI FHIR to a newer version, often there will be changes to the database schema. The **Migrate Database** command can be used to perform a migration from one version to the next.
Note that this feature was added in HAPI FHIR 3.5.0. It is not able to migrate from versions prior to HAPI FHIR 3.4.0. **Please make a backup of your database before running this command!**
The following example shows how to use the migrator utility to migrate between two versions.
```bash
./hapi-fhir-cli migrate-database -d DERBY_EMBEDDED -u "jdbc:derby:directory:target/jpaserver_derby_files;create=true" -n "" -p "" -f V3_4_0 -t V3_5_0
```
You may use the following command to get detailed help on the options:
```bash
./hapi-fhir-cli help migrate-database
```
Note the arguments:
* `-d [dialect]` &ndash; This indicates the database dialect to use. See the detailed help for a list of options
* `-f [version]` &ndash; The version to migrate from
* `-t [version]` &ndash; The version to migrate to
# Oracle Support
Note that the Oracle JDBC drivers are not distributed in the Maven Central repository, so they are not included in HAPI FHIR. In order to use this command with an Oracle database, you will need to invoke the CLI as follows:
```bash
java -cp hapi-fhir-cli.jar ca.uhn.fhir.cli.App migrate-database -d ORACLE_12C -u "[url]" -n "[username]" -p "[password]" -f V3_4_0 -t V3_5_0
```
## Migrating 3.4.0 to 3.5.0+
As of HAPI FHIR 3.5.0 a new mechanism for creating the JPA index tables (HFJ_SPIDX_xxx) has been implemented. This new mechanism uses hashes in place of large multi-column indexes. This improves both lookup times as well as required storage space. This change also paves the way for future ability to provide efficient multi-tenant searches (which is not yet implemented but is planned as an incremental improvement).
This change is not a lightweight change however, as it requires a rebuild of the index tables in order to generate the hashes. This can take a long time on databases that already have a large amount of data.
As a result, in HAPI FHIR JPA 3.6.0, an efficient way of upgrading existing databases was added. Under this new scheme, columns for the hashes are added but values are not calculated initially, database indexes are not modified on the HFJ_SPIDX_xxx tables, and the previous columns are still used for searching as was the case in HAPI FHIR JPA 3.4.0.
In order to perform a migration using this functionality, the following steps should be followed:
* Stop your running HAPI FHIR JPA instance (and remember to make a backup of your database before proceeding with any changes!)
* Modify your `DaoConfig` to specify that hash-based searches should not be used, using the following setting: `myDaoConfig.setDisableHashBasedSearches(true);`
* Make sure that you have your JPA settings configured to not automatically create database indexes and columns using the following setting in your JPA Properties: `extraProperties.put("hibernate.hbm2ddl.auto", "none");`
* Run the database migrator command, including the entry `-x no-migrate-350-hashes` on the command line. For example:
```
./hapi-fhir-cli migrate-database -d DERBY_EMBEDDED -u "jdbc:derby:directory:target/jpaserver_derby_files;create=true" -n "" -p "" -f V3_4_0 -t V3_6_0 -x no-migrate-350-hashes
```
* Rebuild and start your HAPI FHIR JPA server. At this point you should have a working HAPI FHIR JPA 3.6.0 server that is is still using HAPI FHIR 3.4.0 search indexes. Search hashes will be generated for any newly created or updated data but existing data will have null hashes.
* With the system running, request a complete reindex of the data in the database using
an HTTP request such as the following: `POST /$mark-all-resources-for-reindexing`. Note that this is a custom operation built into the HAPI FHIR JPA server. It should be secured in a real deployment, so Authentication is likely required for this call.
* You can track the reindexing process by watching your server logs, but also by using the following SQL executed directly against your database:
```sql
SELECT * FROM HFJ_RES_REINDEX_JOB
```
* When this query no longer returns any rows, the reindexing process is complete.
* At this time, HAPI FHIR should be stopped once again in order to convert it to using the hash based indexes.
* Modify your `DaoConfig` to specify that hash-based searches are used, using the following setting (this is the default setting, so it could also simply be omitted): `myDaoConfig.setDisableHashBasedSearches(false);`
* Execute the migrator tool again, this time omitting the flag option, e.g.
```bash
./hapi-fhir-cli migrate-database -d DERBY_EMBEDDED -u "jdbc:derby:directory:target/jpaserver_derby_files;create=true" -n "" -p "" -f V3_4_0 -t V3_6_0
```
* Rebuild, and start HAPI FHIR JPA again.
# Cascading Deletes
An interceptor called `CascadingDeleteInterceptor` may be registered against the Server. When this interceptor is enabled, cascading deletes may be performed using either of the following:
* The request may include the following parameter: `_cascade=delete`
* The request may include the following header: `X-Cascade: delete`

View File

@ -0,0 +1,74 @@
# Authorization Interceptor
HAPI FHIR 1.5 introduced a new interceptor: [AuthorizationInterceptor](/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.
<p class="helpInfoCalloutBox">
AuthorizationInterceptor has been well tested, but it is impossible to predict every scenario and environment in which HAPI FHIR will be used. Use with caution, and do lots of testing! We welcome feedback and suggestions on this feature. Please get in touch if you'd like to help test, have suggestions, etc.
</p>
The AuthorizationInterceptor works by allowing you to declare permissions based on an individual request coming in. In other words, you could have code that examines an incoming request and determines that it is being made by a Patient with ID 123. You could then declare that the requesting user has access to read and write any resource in compartment "Patient/123", which corresponds to any Observation, MedicationOrder etc with a subject of "`Patient/123`". On the other hand, another request might be detemrined to belong to an administrator user, and could be declared to be allowed to do anything.
The AuthorizationInterceptor is used by subclassing it and then registering your subclass with the `RestfulServer`. The following example shows a subclassed interceptor implementing some basic rules:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/AuthorizationInterceptors.java|patientAndAdmin}}
```
## Using AuthorizationInterceptor in a REST Server
The AuthorizationInterceptor works by examining the client request in order to determine whether "write" operations are legal, and looks at the response from the server in order to determine whether "read" operations are legal.
## Authorizing Read Operations
When authorizing a read operation, the AuthorizationInterceptor always allows client code to execute and generate a response. It then examines the response that would be returned before actually returning it to the client, and if rules do not permit that data to be shown to the client the interceptor aborts the request.
Note that there are performance implications to this mechanism, since an unauthorized user can still cause the server to fetch data even if they won't get to see it. This mechanism should be comprehensive however, since it will prevent clients from using various features in FHIR (e.g. <code>_include</code> or <code>_revinclude</code>) to "trick" the server into showing them date they shouldn't be allowed to see.
See the following diagram for an example of how this works.
<img src="/docs/images/hapi_authorizationinterceptor_read_normal.svg" alt="Write Authorization"/>
## Authorizing Write Operations
Write operations (create, update, etc.) are typically authorized by the interceptor by examining the parsed URL and making a decision about whether to authorize the operation before allowing Resource Provider code to proceed. This means that client code will not have a chance to execute and create resources that the client does not have permissions to create.
See the following diagram for an example of how this works.
<img src="/docs/images/hapi_authorizationinterceptor_write_normal.svg" alt="Write Authorization"/>
<a name="authorizing-sub-operations"/>
## Authorizing Sub-Operations
There are a number of situations where the REST framework doesn't actually know exactly what operation is going to be performed by the implementing server code. For example, if your server implements a <code>conditional update</code> operation, the server might not know which resource is actually being updated until the server code is executed.
Because client code is actually determining which resources are being modified, the server can not automatically apply security rules against these modifications without being provided hints from client code.
In this type of situation, it is important to manually notify the interceptor chain about the "sub-operation" being performed. The following snippet shows how to notify interceptors about a conditional create.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/AuthorizationInterceptors.java|conditionalUpdate}}
```
## Authorizing Patch Operations
The FHIR [patch](http://hl7.org/fhir/http.html#patch) operation presents a challenge for authorization, as the incoming request often contains very little detail about what is being modified.
In order to properly enforce authorization on a server that allows the patch operation, a rule may be added that allows all patch requests, as shown below.
This should be combined with server support for [Authorizing Sub-Operations](#authorizing-sub-operations) as shown above.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/AuthorizationInterceptors.java|patchAll}}
```
## Authorizing Multitenant Servers
The AuthorizationInterceptor has the ability to direct individual rules as only applying to a single tenant in a multitenant server. The following example shows such a rule.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/AuthorizationInterceptors.java|authorizeTenantAction}}
```

View File

@ -0,0 +1,23 @@
# 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).
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.
The consent interceptor has several primary purposes:
** It can reject a resource from being disclosed to the user by examining it while calculating search results. This calculation is performed very early in the process of building search results, in order to ensure that in many cases the user is unaware that results have been removed.
* It can redact results, removing specific elements before they are returned to a client.
* It can create audit trail records (e.g. using an AuditEvent resource)
* It can apply consent directives (e.g. by reading relevant Consent resources)
* 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:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ConsentInterceptors.java|service}}
```

View File

@ -0,0 +1,36 @@
# REST Server Security: Introduction
Security is a complex topic which goes far beyond the scope of FHIR or HAPI. Every system and architecture operates in a different set of rules, and has different security requirements.
As such, HAPI FHIR does not provide a single one-size-fits-all security layer. Instead, it provides a numnber of useful tools and building blocks that can be built around as a part of your overall security architecture.
Because HAPI FHIR's REST server is based on the Servlet API, you may use any security mechanism which works in that environment. Some serlvet containers may provide security layers you can plug into. The rest of this page does not explore that method, but rather looks at HAPI FHIR hooks that can be used to implement FHIR specific security.
# Authentication vs Authorization
Background reading: [Wikipedia - Authentication](https://en.wikipedia.org/wiki/Authentication)
Server security is divided into three topics:
* **Authentication (AuthN):** Is verifying that the user is who they say they are. This is typically accomplished by testing a username/password in the request, or by checking a "bearer token" in the request.
* **Authorization (AuthZ):** Is verifying that the user is allowed to perform the given action. For example, in a FHIR application you might use AuthN to test that the user making a request to the FHIR server is allowed to access the server, but that test might determine that the requesting user is not permitted to perform write operations and therefore block a FHIR <code>create</code> operation. This is AuthN and AuthZ in action.
* **Consent and Audit:** Is verifying that a user has rights to see/modify the specific resources they are requesting, applying any directives to mask data being returned to the client (either partially or completely), and creating a record that the event occurred.
# Authentication Interceptors
The [Server Interceptor](/docs/interceptors/server_interceptors.html) framework can provide an easy way to test for credentials. The following example shows a simple custom interceptor which tests for HTTP Basic Auth.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/SecurityInterceptors.java|basicAuthInterceptor}}
```
## HTTP Basic Auth
Note that if you are implementing HTTP Basic Auth, you may want to return a <code>WWW-Authenticate</code> header with the response. The following snippet shows how to add such a header with a custom realm:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/SecurityInterceptors.java|basicAuthInterceptorRealm}}
```

View File

@ -0,0 +1,24 @@
# 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).
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.
This could be used, for example, to allow the user to perform a search for:
```url
http://baseurl/Observation?category=laboratory
```
...and then receive results as though they had requested:
```url
http://baseurl/Observation?subject=Patient/123&amp;category=laboratory
```
An example of this interceptor follows:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/AuthorizationInterceptors.java|narrowing}}
```

View File

@ -0,0 +1,22 @@
# HAPI FHIR JPA Architecture
<img src="/hapi-fhir/docs/images/jpa_architecture.png" alt="Architecture" align="right"/>
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.
The resource providers also extend a superclass which implements all of the other FHIR methods, such as Read, Create, Delete, etc.
Note that these resource providers are generated as a part of the HAPI build process, so they are not checked into Git. The resource providers do not actually implement any of the logic in searching, updating, etc. They simply receive the incoming HTTP calls (via the RestfulServer) and pass along the incoming requests to the DAOs.
* **HAPI DAOs:** The DAOs actually implement all of the database business logic relating to the storage, indexing, and retrieval of FHIR resources, using the underlying JPA API.
* **Hibernate:** The HAPI JPA Server uses the JPA library, implemented by Hibernate. No Hibernate specific features are used, so the library should also work with other providers (e.g. Eclipselink) but it is not tested regularly with them.
* **Database:** The RESTful server uses an embedded Derby database, but can be configured to talk to [any database supported by Hibernate](https://developer.jboss.org/wiki/SupportedDatabases2?_sscc=t).
# Schema
This implementation uses a fairly simple table design, with a single table being used to hold resource bodies (which are stored as CLOBs, optionally GZipped to save space) and a set of tables to hold search indexes, tags, history details, etc. This design has proven to be very scalable and flexible, and has been successfully used in large scale production architectures. That said,

View File

@ -0,0 +1,3 @@
# Getting Started with HAPI FHIR JPA Server
The recommended way to get started with the JPA Server is to use the [hapi-fhir-jpaserver-starter](https://github.com/hapifhir/hapi-fhir-jpaserver-starter

View File

@ -0,0 +1,125 @@
# 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.
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.
# Getting Started
The recommended way to get started with HAPI's JPA server module is
to begin with the starter project. This project can be found at the following link: [https://github.com/hapifhir/hapi-fhir-jpaserver-starter](https://github.com/hapifhir/hapi-fhir-jpaserver-starter)
This project is a fully contained FHIR server, supporting all standard operations (read/create/delete/etc). It bundles an embedded instance of the <a href="http://h2database.com">H2 Java Database</a> so that the server can run without depending on any external database, but it can also be configured to use an installation of Oracle, Postgres, etc.
# Configuration Options
## External/Absolute Resource References
Clients may sometimes post resources to your server that contain absolute resource references. For example, consider the following resource:
```xml
<Patient xmlns="http://hl7.org/fhir">
<id value="patient-infant-01"/>
<name>
<use value="official"/>
<family value="Miller"/>
<given value="Samuel"/>
</name>
<managingOrganization>
<reference value="http://example.com/fhir/Organization/123"/>
</managingOrganization>
</Patient>
```
By default, the server will reject this reference, as only local references are permitted by the server. This can be changed however.
If you want the server to recognize that this URL is actually a local reference (i.e. because the server will be deployed to the base URL `http://example.com/fhir/`) you can configure the server to recognize this URL via the following DaoConfig setting:
```java
@Bean
public DaoConfig daoConfig() {
DaoConfig retVal = new DaoConfig();
// ... other config ...
retVal.getTreatBaseUrlsAsLocal().add("http://example.com/fhir/");
return retVal;
}
```
On the other hand, if you want the server to be configurable to allow remote references, you can set this with the confguration below. Using the `setAllowExternalReferences` means that it will be possible to search for references that refer to these external references.
```java
@Bean
public DaoConfig daoConfig() {
DaoConfig retVal = new DaoConfig();
// Allow external references
retVal.setAllowExternalReferences(true);
// If you are allowing external references, it is recommended to
// also tell the server which references actually will be local
retVal.getTreatBaseUrlsAsLocal().add("http://mydomain.com/fhir");
return retVal;
}
```
## Logical References
In some cases, you may have references which are <i>Logical References</i>,
which means that they act as an identifier and not necessarily as a literal
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 neccesarily 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-)).
For example:
```java
// Treat specific URL as logical
myDaoConfig.getTreatReferencesAsLogical().add("http://mysystem.com/ValueSet/cats-and-dogs");
// Treat all references with given prefix as logical
myDaoConfig.getTreatReferencesAsLogical().add("http://mysystem.com/mysystem-vs-*");
```
# Search Result Caching
By default, search results will be cached for one minute. This means that if a client performs a search for <code>Patient?name=smith</code> and gets back 500 results, if a client performs the same search within 60000 milliseconds the previously loaded search results will be returned again. This also means that any new Patient resources named "Smith" within the last minute will not be reflected in the results.
Under many normal scenarios this is a n acceptable performance tradeoff, but in some cases it is not. If you want to disable caching, you have two options:
### Globally Disable / Change Caching Timeout
You can change the global cache using the following setting:
```java
myDaoConfig.setReuseCachedSearchResultsForMillis(null);
```
### Disable Cache at the Request Level
Clients can selectively disable caching for an individual request using the Cache-Control header:
```http
Cache-Control: no-cache
```
### Disable Paging at the Request Level
If the client knows that they will only want a small number of results (for example, a UI containing 20 results is being shown and the client knows that they will never load the next page of results) the client
may also use the <code>no-store</code> directive along with a HAPI FHIR extension called <code>max-results</code> in order to specify that only the given number of results should be fetched. This directive disabled paging entirely for the request and causes the request to return immediately when the given number of results is found. This can cause a noticeable performance improvement in some cases.
```http
Cache-Control: no-store, max-results=20
```
# Additional Information
* [This page](https://www.openhealthhub.org/t/hapi-terminology-server-uk-snomed-ct-import/592) has information on loading national editions (UK specifically) of SNOMED CT files into the database.
# Cascading Deletes
An interceptor called `CascadingDeleteInterceptor` may be registered against the Server. When this interceptor is enabled, cascading deletes may be performed using either of the following:
* The request may include the following parameter: `_cascade=delete`
* The request may include the following header: `X-Cascade: delete`

View File

@ -0,0 +1,71 @@
# HAPI FHIR JPA Upgrade Guide
HAPI FHIR JPA is a constantly evolving product, with new features being added to each new version of the library. As a result, it is generally necessary to execute a database migration as a part of an upgrade to HAPI FHIR.
When upgrading the JPA server from one version of HAPI FHIR to a newer version, often there will be changes to the database schema. The **Migrate Database** command can be used to perform a migration from one version to the next.
Note that this feature was added in HAPI FHIR 3.5.0. It is not able to migrate from versions prior to HAPI FHIR 3.4.0. **Please make a backup of your database before running this command!**
The following example shows how to use the migrator utility to migrate between two versions.
```bash
./hapi-fhir-cli migrate-database -d DERBY_EMBEDDED -u "jdbc:derby:directory:target/jpaserver_derby_files;create=true" -n "" -p "" -f V3_4_0 -t V3_5_0
```
You may use the following command to get detailed help on the options:
```bash
./hapi-fhir-cli help migrate-database
```
Note the arguments:
* `-d [dialect]` &ndash; This indicates the database dialect to use. See the detailed help for a list of options
* `-f [version]` &ndash; The version to migrate from
* `-t [version]` &ndash; The version to migrate to
# Oracle Support
Note that the Oracle JDBC drivers are not distributed in the Maven Central repository, so they are not included in HAPI FHIR. In order to use this command with an Oracle database, you will need to invoke the CLI as follows:
```bash
java -cp hapi-fhir-cli.jar ca.uhn.fhir.cli.App migrate-database -d ORACLE_12C -u "[url]" -n "[username]" -p "[password]" -f V3_4_0 -t V3_5_0
```
## Migrating 3.4.0 to 3.5.0+
As of HAPI FHIR 3.5.0 a new mechanism for creating the JPA index tables (HFJ_SPIDX_xxx) has been implemented. This new mechanism uses hashes in place of large multi-column indexes. This improves both lookup times as well as required storage space. This change also paves the way for future ability to provide efficient multi-tenant searches (which is not yet implemented but is planned as an incremental improvement).
This change is not a lightweight change however, as it requires a rebuild of the index tables in order to generate the hashes. This can take a long time on databases that already have a large amount of data.
As a result, in HAPI FHIR JPA 3.6.0, an efficient way of upgrading existing databases was added. Under this new scheme, columns for the hashes are added but values are not calculated initially, database indexes are not modified on the HFJ_SPIDX_xxx tables, and the previous columns are still used for searching as was the case in HAPI FHIR JPA 3.4.0.
In order to perform a migration using this functionality, the following steps should be followed:
* Stop your running HAPI FHIR JPA instance (and remember to make a backup of your database before proceeding with any changes!)
* Modify your `DaoConfig` to specify that hash-based searches should not be used, using the following setting: `myDaoConfig.setDisableHashBasedSearches(true);`
* Make sure that you have your JPA settings configured to not automatically create database indexes and columns using the following setting in your JPA Properties: `extraProperties.put("hibernate.hbm2ddl.auto", "none");`
* Run the database migrator command, including the entry `-x no-migrate-350-hashes` on the command line. For example:
```
./hapi-fhir-cli migrate-database -d DERBY_EMBEDDED -u "jdbc:derby:directory:target/jpaserver_derby_files;create=true" -n "" -p "" -f V3_4_0 -t V3_6_0 -x no-migrate-350-hashes
```
* Rebuild and start your HAPI FHIR JPA server. At this point you should have a working HAPI FHIR JPA 3.6.0 server that is is still using HAPI FHIR 3.4.0 search indexes. Search hashes will be generated for any newly created or updated data but existing data will have null hashes.
* With the system running, request a complete reindex of the data in the database using
an HTTP request such as the following: `POST /$mark-all-resources-for-reindexing`. Note that this is a custom operation built into the HAPI FHIR JPA server. It should be secured in a real deployment, so Authentication is likely required for this call.
* You can track the reindexing process by watching your server logs, but also by using the following SQL executed directly against your database:
```sql
SELECT * FROM HFJ_RES_REINDEX_JOB
```
* When this query no longer returns any rows, the reindexing process is complete.
* At this time, HAPI FHIR should be stopped once again in order to convert it to using the hash based indexes.
* Modify your `DaoConfig` to specify that hash-based searches are used, using the following setting (this is the default setting, so it could also simply be omitted): `myDaoConfig.setDisableHashBasedSearches(false);`
* Execute the migrator tool again, this time omitting the flag option, e.g.
```bash
./hapi-fhir-cli migrate-database -d DERBY_EMBEDDED -u "jdbc:derby:directory:target/jpaserver_derby_files;create=true" -n "" -p "" -f V3_4_0 -t V3_6_0
```
* Rebuild, and start HAPI FHIR JPA again.

View File

@ -0,0 +1,8 @@
# Getting Started with HAPI FHIR Plain Server
Two starter projects are maintained as examples that can be used as a base for a HAPI FHIR Plain Server project. These examples can be used as a guide by examining them or copying relevant bits into your oown project, or they can be used to bootstrap a new project by copying the entire project contents and modifying directly.
* **[hapi-fhirstarters-rest-server-skeleton](https://github.com/FirelyTeam/fhirstarters/tree/master/java/hapi-fhirstarters-rest-server-skeleton/)** &ndash; This project is a basic skeleton showing the minimal components necessary in order to get started with HAPI FHIR Plain Server.
* **[hapi-fhirstarters-simple-server](https://github.com/FirelyTeam/fhirstarters/tree/master/java/hapi-fhirstarters-simple-server/)** &ndash; This project is a more complete example containing several example resource providers and an [interceptor](/docs/interceptors/).

View File

@ -0,0 +1,174 @@
# Creating A Plain Server
HAPI FHIR provides a built-in mechanism for adding FHIR's RESTful Server capabilities to your applications. The HAPI RESTful Server is Servlet based, so it should be easy to deploy to any of the many compliant containers that exist.
Setup is mostly done using simple annotations, which means that it should be possible to create a FHIR compliant server quickly and easily.
# Defining Resource Providers
The first step in creating a FHIR RESTful Server is to define one or more resource providers. A resource provider is a class which is able to supply exactly one type of resource to be served up.
For example, if you wish to allow your server to serve up Patient, Observation and Location resources, you will need three resource providers.
See [Resource Providers](./resource_providers.html) for information on how to create these classes.
# Deploying
Once you have created your resource providers and your restful server class, you can bundle these into a WAR file and you are ready to deploy to any JEE container (Tomcat, Websphere, Glassfish, etc).
Assuming that you are using a build tool such as Apache Maven to build your project, you can create your WAR file simply by building the project.
```
mvn install
```
Once the build is complete, a file called `[projectname].war` will be found in the `target/` directory. This file can be deployed to the container/application server of your choice. Deploying WAR files to an application server is beyond the scope of this page, but there are many good tutorials on how to do this available on the web.
# Testing Using Jetty
Many of the HAPI FHIR sample projects take advantage of the *Maven Jetty Plugin* to provide an easy testing mechanism. This plugin can be used to automatically compile your code and deploy it to a local server (without needing to install anything additional) using a simple command.
To execute the Maven Jetty Plugin:
```
mvn jetty:run
```
# Server Base URL (Web Address)
The server will return data in a number of places that includes the complete "identity" of a resource. Identity in this case refers to the web address that a user can use to access the resource.
For instance, if your server is hosted at `http://foo.com/fhir`, and your resource provider returns a Patient resource with the ID `123`, the server should translate that ID to `http://foo.com/fhir/Patient/123`. This complete identity URL is used in response headers (e.g. the `Location` header) as well as in Bundle resource contents (e.g. the Bundle entry "fullUrl" property).
The server will attempt to determine what the base URL should be based on what the request it receives looks like, but if it is not getting the right address you may wish to use a different "address strategy".
## Hardcoded Address Strategy
The simplest way to do this is to configure the server to use a hardcoded base URL, which means that the server won't try to figure out the "http://foo.com/fhir" part of the URL but will instead just use a fixed value you supply.
The hardcoded address strategy is particularly useful in cases where the server is not aware of the external address used to access it, as is often the case in network architectures where a reverse proxy, API gateway, or other network equipment is present.
This strategy is shown in the following example:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ExampleProviders.java|addressStrategy}}
```
## 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.
<a name="capabilities"/>
# Capability Statement / Server Metadata
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.
## Enhancing the Generated CapabilityStatement
If you have a need to add your own content (special extensions, etc.) to your server's conformance statement, but still want to take advantage of HAPI's automatic CapabilityStatement generation, you may wish to extend the built-in generator class.
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)
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.
# Controlling Response Contents / Encoding / Formatting
FHIR allows for the a number of special behaviours where only certain portions of resources are returned, instead of the entire resource body. These behaviours are automatically supported in HAPI FHIR Plain Server and no additional effort needs to be taken.
The following behaviours are automatically supported by the HAPI server:
<table class="table">
<thead>
<tr>
<td><b>Parameter</b></td>
<td><b>Description</b></td>
</tr>
</thead>
<tbody>
<tr>
<td>_summary=true</td>
<td>
Resources will be returned with any elements not marked as summary elements
omitted.
</td>
</tr>
<tr>
<td>_summary=text</td>
<td>
Only the narrative portion of returned resources will be returned. For a read/vread
operation, the narrative will be served with a content type of <code>text/html</code>.
for other operations, a Bundle will be returned but resources will only include
the text element.
</td>
</tr>
<tr>
<td>_summary=data</td>
<td>
The narrative (text) portion of the resource will be omitted.
</td>
</tr>
<tr>
<td>_summary=count</td>
<td>
For a search, only Bundle.count will be returned.
</td>
</tr>
<tr>
<td>_elements=[element names]</td>
<td>
Only the given top level elements of returned resources will be returned, e.g for
a Patient search: <code>_elements=name,contact</code>
</td>
</tr>
<tr>
<td>_pretty=true</td>
<td>
Request that the server pretty-print the response (indent the data over multiple lines for easier human readability).
</td>
</tr>
</tbody>
</table>
## Extended Elements Support
The HAPI FHIR server may be configured using the `RestfulServer#setElementsSupport` to enable extended support for the <code>_elements</code> filter.
In standard mode, elements are supported exactly as described in the <a href="http://hl7.org/fhir/search.html#elements">Elements Documentation</a> in the FHIR specification.
In extended mode, HAPI FHIR provides the same behaviour as described in the FHIR specification, but also enabled the following additional options:
* Values may be prepended using Resource names in order to apply the elements filter to multiple resources. For example, the following parameter could be used to apply elements filtering to both the DiagnosticReport and Observation resource in a search result:
```url
http://base/Patient?_elements=DiagnosticReport.subject,DiagnosticReport.result,Observation.value
```
* Values may be prepended with a wildcard star in order to apply them to all resource types. For example, the following parameter could be used to include the <code>subject</code> field in all resource types:
```url
http://base/Patient?_elements=*.subject
```
* Values may include complex paths. For example, the following parameter could be used to include only the code on a coded element:
```url
http://base/Patient?_elements=Procedure.reasonCode.coding.code
```
* Elements may be excluded using the <code>:exclude</code> modifier on the elements parameter. For example, the following parameter could be used to remove the resource metadata (meta) element from all resources in the response:
```url
http://base/Patient?_elements:exclude=*.meta
```
Note that this can be used to suppress the `SUBSETTED` tag which is automatically added to resources when an `_elements` parameter is applied.

View File

@ -0,0 +1,22 @@
# Multitenency
If you wish to allow a single endpoint to support multiple tenants, you may supply the server with a multitenancy provider.
This means that additional logic will be performed during request parsing to determine a tenant ID, which will be supplied to resource providers. This can be useful in servers that have multiple distinct logical pools of resources hosted on the same infrastructure.
## URL Base Multitenancy
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:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/Multitenancy.java|enableUrlBaseTenantIdentificationStrategy}}
```
Your resource providers can then use a RequestDetails parameter to determine the tenant ID:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/Multitenancy.java|resourceProvider}}
```

View File

@ -0,0 +1,50 @@
# Paging Responses
The **Search** and **History** operations both return a bundle which contain zero or more resources. FHIR RESTful servers may optionaly support paging responses, meaning that (for example) if a search returns 500 resources, the server can return a bundle containing only the first 20 and a link which will return the next 20, etc.
By default, RESTful servers will not page, but will rather return all resources immediately in a single bundle. However, you can take advantage of built-in paging functionality to automatically add paging links to generated Bundle resources, and to handle these links by requesting further data.
There are two complimentary parts to the HAPI FHIR server paging support: paging providers, and bundle providers.
## 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.
A paging provider provides two key methods:
* `String storeResultList(RequestDetails, IBundleProvider)`, which takes a bundle provider (see below) and stores it for later retrieval. This might be by simply keeping it in memory, but it might also store it on disk, in a database, etc. This method must return a textual ID which can be used to retrieve this list later.
* `retrieveResultList(RequestDetails, String)`</code>, which takes an ID obtained by a previous call to `storeResultList` and returns the corresponding result list.
Note that the IPagingProvider is intended to be simple and implementable and you are encouraged to provide your own implementations.
The following example shows a server implementation with paging support.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/PagingServer.java|provider}}
```
# 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).
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.
One implementation of a bundle provider is shown below. This provider example works by only keeping the resource IDs in memory, but there are other possible implementation strategies that would work as well.
Note that the IBundleProvider is intended to be simple and implementable and you are encouraged to provide your own implementations.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/PagingPatientProvider.java|provider}}
```
## Using Named Pages
By default, the paging system uses parameters that are embedded into the page links for the start index and the page size. This is useful for servers that can retrieve arbitrary offsets within a search result. For example, if a given search can easily retrieve "items 5-10 from the given search", then the mechanism above works well.
Another option is to use "named pages", meaning that each page is simply assigned an ID by the server, and the next/previous page is requested using this ID.
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.

View File

@ -0,0 +1,112 @@
# Resource Providers and Plain Providers
There are two types of providers that can be registered against a HAPI FHIR Plain Server:
* Resource Providers are POJO classes that implement operations for a specific resource type
* Plain Providers are POJO classes that implement operations for multiple resource types, or for system-level operations.
<a name="resource-providers"/>
# 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.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProvider.java|provider}}
```
## 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.
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.
## Create a Server
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.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ExampleRestfulServlet.java|servlet}}
```
<a name="plain-providers"/>
# Plain Providers
In addition to **Resource Providers**, which are resource-type specific, a second kind of provider known as **Plain Providers**. These providers can be used both to define resource operations that apply to multiple resource types, and to define opoerations that operate at the server level.
## Resource Operatipns
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**.
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:
```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.
Once you have defined your plain providers, they are passed to the server in a similar way to the resource providers.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ExampleProviders.java|plainProviderServer}}
```
# 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.
In addition, there are several parameters you may add in order to meet specific needs of your application.
## Accessing the underlying Servlet Request/Response
In some cases, it may be useful to have access to the underlying HttpServletRequest and/or HttpServletResponse objects. These may be added by simply adding one or both of these objects as method parameters.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|underlyingReq}}
```
<a name="exceptions"/>
# REST Exception/Error Handling
Within your RESTful operations, you will generally be returning resources or bundles of resources under normal operation. During execution you may also need to propagate errors back to the client for a variety of reasons.
## Automatic Exception Handling
By default, HAPI generates appropriate error responses for a several built-in conditions. For example, if the user makes a request for a resource type that does not exist, or tries to perform a search using an invalid parameter, HAPI will automatically generate an `HTTP 400 Invalid Request`, and provide an OperationOutcome resource as response containing details about the error.
Similarly, if your method implementation throws any exceptions (checked or unchecked) instead of returning normally, the server will usually (see below) automatically generate an `HTTP 500 Internal Error` and generate an OperationOutcome with details about the exception.
## Generating Specific HTTP Error Responses
In many cases, you will want to respond to client requests with a specific HTTP error code (and possibly your own error message too). Sometimes this is a requirement of the FHIR specification. (e.g. the "validate" operation requires a response of `HTTP 422 Unprocessable Entity` if the validation fails).
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 ini a specific way to certani conditions.
To customize the error that is returned by HAPI's server methods, you shuld 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.
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).
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.
## Returning an OperationOutcome for Errors
By default, HAPI will automatically generate an OperationOutcome which contains details about the exception that was thrown. You may wish to provide your own OperationOutcome instead. In this case, you may pass one into the constructor of the exception you are throwing.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ServerExceptionsExample.java|returnOO}}
```
# 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).
This method will be invoked once by the RestfulServer when it is shutting down.

View File

@ -0,0 +1,447 @@
# 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.
<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.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|read}}
```
Example URL to invoke this method:
```url
http://fhir.example.com/Patient/111
```
The following snippet shows how to define a client interface to handle a read method.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|clientReadInterface}}
```
<a name="instance_vread" />
# 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 request.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|vread}}
```
Example URL to invoke this method:
```url
http://fhir.example.com/Patient/111/_history/2
```
<a name="instance_update" />
# Instance Level - Update
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[]).
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.
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.
The following snippet shows how to define an update method on a server:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|update}}
```
Example URL to invoke this method (this would be invoked using an HTTP PUT, with the resource in the PUT body):
```url
http://fhir.example.com/Patient
```
The following snippet shows how the corresponding client interface would look:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|updateClient}}
```
## Conditional Updates
If you wish to suport 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.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|updateConditional}}
```
Example URL to invoke this method (this would be invoked using an HTTP PUT, with the resource in the PUT body):
```url
http://fhir.example.com/Patient?identifier=system%7C00001
```
<a name="raw_update_access"/>
## 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).
The following example shows how to use these additonal data elements.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|updateRaw}}
```
<a name="prefer"/>
## Prefer Header / Returning the resource body
If you want to allow clients to request that the server return the resource body as a result of the transaction, you may wish to return the updated resource in the returned MethodOutcome.
In this type of request, the client adds a header containing `Prefer: return=representation` which indicates to the server that the client would like the resource returned in the response.
In order for the server to be able to honour this request, the server method should add the updated resource to the MethodOutcome object being returned, as shown in the example below.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|updatePrefer}}
```
## Contention Aware Updating
As of FHIR DSTU2, FHIR uses the `ETag` header to provide *conention aware updating*. Under this scheme, a client may create a request that contains an ETag specifying the version, and the server will fail if the given version is not the latest version.
Such a request is shown below. In the following example, the update will only be applied if resource "Patient/123" is currently at version "3". Otherwise, it will fail with an `HTTP 409 Conflict` error.
```http
PUT [serverBase]/Patient/123
If-Match: W/"3"
Content-Type: application/fhir+json
{ ..resource body.. }
```
If a client performs a contention aware update, the ETag version will be placed in the version part of the IdDt/IdType that is passed into the method. For example:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|updateEtag}}
```
<a name="instance_delete" />
# 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.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|delete}}
```
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.
Example URL to invoke this method (HTTP DELETE):
```url
http://fhir.example.com/Patient/111
```
## Conditional Deletes
The FHIR specification also allows "conditional deletes". A conditional delete uses a search style URL instead of a read style URL, and deletes a single resource if it matches the given search parameters. The following example shows how to invoke a conditional delete.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|deleteConditional}}
```
Example URL to perform a conditional delete (HTTP DELETE):
```url
http://fhir.example.com/Patient?identifier=system%7C0001
```
# Instance Level - Patch
HAPI FHIR includes basic support for the [patch](http://hl7.org/implement/standards/fhir/http.html#patch) operation. This support allows you to perform patches, but does not include logic to actually implement resource patching in the server framework (note that the JPA server does include a patch implementation).
The following snippet shows how to define a patch method on a server:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/PatchExamples.java|patch}}
```
<a name="type_create" />
# Type Level - Create
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 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.
The following snippet shows how to define a server create method:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|create}}
```
Example URL to invoke this method (this would be invoked using an HTTP POST, with the resource in the POST body):
```url
http://fhir.example.com/Patient
```
The following snippet shows how the corresponding client interface would look:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|createClient}}
```
## Conditional Creates
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.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|createConditional}}
```
Example HTTP transaction to perform a conditional create:
```http
POST http://fhir.example.com/Patient
If-None-Exist: Patient?identifier=system%7C0001
Content-Type: application/fhir+json
{ ...resource body... }
```
## Prefer Header / Returning the resource body
If you wish to allow your server to honour the `Prefer` header, the same mechanism shown above for [Prefer Header for Updates](#prefer) should be used.
## Accessing The Raw Resource Payload
The create operation also supports access to the raw payload, using the same semantics as raw payload access [for the update operation](#raw_update_access).
<a name="type_search" />
# Type Level - Search
The [search](http://hl7.org/implement/standards/fhir/http.html#search) operation returns a bundle with zero-to-many resources of a given type, matching a given set of parameters.
Searching is a very powerful and potentially very complicated operation to implemenmt, with many possible parameters and combinations of parameters. See [REST Operations: Search](./rest_operations_search.html) for details on how to create search methods.
<a name="type_validate" />
# Type Level - Validate
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 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 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 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.
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:
* **[@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.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)
Example URL to invoke this method (this would be invoked using an HTTP POST, with a Parameters resource in the POST body):
```url
http://fhir.example.com/Patient/$validate
```
<a name="system_capabilities" />
# System Level - Capabilities
FHIR defines that a FHIR Server must be able to export a Capability Statement (formerly called a Conformance Statement), which is an instance of the [CapabilityStatement](http://hl7.org/implement/standards/fhir/CapabilityStatement.html) resource describing the server itself.
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.
An example provider is shown below.
```java
{{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:
```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:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|metadataClientUsage}}
```
<a name="system_transaction" />
# System Level - Transaction
The [transaction](http://hl7.org/implement/standards/fhir/http.html#transaction) action is among the most challenging parts of the FHIR specification to implement. It allows the user to submit a bundle containing a number of resources to be created/updated/deleted as a single atomic transaction.
HAPI provides a skeleton for implementing this action, although most of the effort will depend on the underlying implementation. The following example shows how to define a <i>transaction</i> method.
```java
{{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)`.
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).
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):
```http
POST http://fhir.example.com/
Content-Type: application/fhir+json
{
"resourceType": "Bundle",
"type": "transaction",
"entry": [ ...entries... ]
}
```
<a name="system_search" />
# System Level - Search
Not yet implemented - Get in touch if you would like to help!
<a name="history" />
# History (Instance, Type, Server)
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:
* 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 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 **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).
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 [@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).
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|history}}
```
The following snippet shows how to define various history methods in a client.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|historyClient}}
```
# Exceptions
When implementing a server operation, there are a number of failure conditions specified. For example, an [Instance Read](#instance_read) request might specify an unknown resource ID, or a [Type Create](#type_create) request might contain an invalid resource which can not be created.
See [REST Exception Handling](./resource_providers.html#exceptions) for information on available exceptions.
<a name="tags" />
# Tags
FHIR RESTful servers may support a feature known as tagging. Tags are a set of named flags called which use a FHIR Coding datatype (meaning that they have a system, value, and display just like any other coded field).
Tags have very specific semantics, which may not be obvious simply by using the HAPI API. It is important to review the specification [Tags Documentation](http://hl7.org/implement/standards/fhir/http.html#tags) before attempting to implement tagging in your own applications.
## Accessing Tags in a Read / VRead / Search Method
Tags are stored within a resource object, in the Resource.meta element.
In a server implementation, you may populate your tags into the returned resource(s) and HAPI will automatically place these tags into the response headers (for read/vread) or the bundle category tags (for search). The following example illustrates how to return tags from a server method. This example shows how to supply tags in a read method, but the same approach applies to vread and search operations as well.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|readTags}}
```
In a client operation, you simply call the read/vread/search method as you normally would (as described above), and if any tags have been returned by the server, these may be accessed from the resource metadata.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|clientReadTags}}
```
## Setting Tags in a Create/Update Method
Within a [Type Create](#type_create) or [Instance Update](#instance_update) method, it is possible for the client to specify a set of tags to be stored along with the saved resource instance.
Note that FHIR specifies that in an update method, any tags supplied by the client are copied to the newly saved version, as well as any tags the existing version had.
To work with tags in a create/update method, the pattern used in the read examples above is simply revered. In a server, the resource which is passed in will be populated with any tags that the client supplied:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|createTags}}
```
# Handling _summary and _elements
The `_summary` and `_elements` parameters are automatically handled by the server, so no coding is required to make this work.
However, if you wish to add parameters to manually handle these fields, the following example shows how to access these. This can be useful if you have an architecture where it is more work for the database/storage engine to load all fields.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|summaryAndElements}}
```
<a name="compartments" />
# Compartments
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.
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.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|searchCompartment}}
```
Example URL to invoke this method:
```url
http://fhir.example.com/Patient/123/Condition
```

View File

@ -0,0 +1,106 @@
# REST Operations: Operations Framework
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 conventon `$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.
## Providers
To define an operation, a method should be placed in a [Resource Provider class](./resource_providers.html#resource-providers) if the operation works against a resource type/instance (e.g. `Patient/$everything`), or on a [Plain Provider class](./resource_providers.html#plain-providers) if the operation works against the server (i.e. it is global and not resource specific).
# 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.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ServerOperations.java|patientTypeOperation}}
```
Example URL to invoke this operation:
```url
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 show how to implement the `Patient/[id]/$everything` operation.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ServerOperations.java|patientInstanceOperation}}
```
Example URL to invoke this operation:
```url
http://fhir.example.com/Patient/123/$everything
```
# Server-Level Operations
Server-level operations do not operate on a specific resource type or instance, but rather operate globally on the server itself. The following example show how to implement the a server-level operation. Note that the `concept` parameter in the example has a cardinality of `0..*`, so a ``List<Coding>` is used as the parameter type.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ServerOperations.java|serverOperation}}
```
Example URL to invoke this operation (HTTP request body is Parameters resource):
```url
http://fhir.example.com/$closure
```
# Using Search Parameter Types
FHIR allows operation parameters to be of a [Search parameter type](http://hl7.org/fhir/search.html#ptypes) (e.g. token) instead of a FHIR datatype (e.g. Coding).
To use a search parameter type, any of the search parameter types listed in [Rest Operations: Search](./rest_operations_search.html) may be used. For example, the following is a simple operation method declaration using search parameters:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ServerOperations.java|searchParamBasic}}
```
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
```
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).
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).
For example:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ServerOperations.java|searchParamAdvanced}}
```
# 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.
# Accepting HTTP GET
The FHIR specification allows for operations to be invoked using an HTTP GET instead of an HTTP POST **only** if the following two conditions are met:
* All parameters have primtive datatype values
* 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.
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.
The following example shows an operation that parses the request and generates a response (by echoing back the request).
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ServerOperations.java|manualInputAndOutput}}
```

View File

@ -0,0 +1,347 @@
# Rest Operations: Search
This page describes how to add various FHIR search features to your resource/plain providers.
# Search with No Parameters
The following example shows a search with no parameters. This operation should return all resources of a given type (this obviously doesn't make sense in all contexts, but does for some resource types).
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|searchAll}}
```
Example URL to invoke this method:
```url
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).
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.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|searchStringParam}}
```
Example URL to invoke this method:
```url
http://fhir.example.com/Patient?family=SMITH
```
# Search Parameters: Token/Identifier
The "token" type is used for parameters which have two parts, such as an identifier (which has a system URI, as well as the actual identifier) or a code (which has a code system, as well as the actual code). For example, the search below can be used to search by identifier (e.g. search for an MRN).
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|searchIdentifierParam}}
```
Example URL to invoke this method:
```url
http://fhir.example.com/Patient?identifier=urn:foo|7000135
```
# Search Parameters: Date (Simple)
The FHIR specification provides a sytax for specifying dates+times (but for simplicity we will just say dates here) as search criteria.
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.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|dates}}
```
Example URL to invoke this method:
```url
http://fhir.example.com/Observation?birthdate=gt2011-01-02
```
Invoking a client of thie type involves the following syntax:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|dateClient}}
```
<a name="DATE_RANGES" />
# Search Parameters: Date (Ranges)
A common scenario in searches is to allow searching for resources with values (i.e timestamps) within a range of dates.
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).
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|dateRange}}
```
Example URL to invoke this method:
```url
http://fhir.example.com/Observation?subject.identifier=7000135&date=gt2011-01-01&date=lt2011-02-01
```
Invoking a client of this type involves the following syntax:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|dateClient}}
```
## Unbounded Date Ranges
Note that when using a date range parameter, it is also possible for the client to request an *unbounded* range. In other words, a range that only a start date and no end date, or vice versa.
An example of this might be the following URL, which refers to any Observation resources for the given MRN and having a date after 2011-01-01.
```url
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`.
# Search Parameters: Quantity
Quantity parameters allow a number with units and a comparator.
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)
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|quantity}}
```
Example URL to invoke this method:
```url
http://fhir.example.com/Observation?value-quantity=lt123.2||mg|http://unitsofmeasure.org
```
# Search Parameters: Resource Reference
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.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|referenceSimple}}
```
# 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).
The net result in the query string would look like:
```url
http://fhir.example.com/DiagnosticReport?subject.family=SMITH
```
What this query says is "fetch me all of the DiagnosticReport resources where the **subject** (Patient) of the report has the **family** (name) of 'SMITH'".
There are two ways of dealing with chained parameters in your methods: static chains and dynamic chains. Both are equally valid, although dyamic chains might lead to somewhat more compact and readable code.
<a name="dynamic_chains"/>
## Dynamic Chains
Chained values must be explicitly declared through the use of a whitelist (or blacklist). The following example shows how to declare a report with an allowable chained parameter:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|referenceWithChain}}
```
You may also specify the whitelist value of <code>""</code> to allow an empty chain (e.g. the resource ID) and this can be combined with other values, as shown below:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|referenceWithChainCombo}}
```
If you are handling multiple types of chained parameters in a single method, you may want to convert the reference parameter type into something more convenient before using its value. The following example shows how to do that.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|referenceWithDynamicChain}}
```
## Static Chains
It is also possible to explicitly state a chained value right in the parameter name. This is useful if you want to only support a search by a specific given chained parameter. It has the added bonus that you can use the correct parameter type of the chained parameter (in this case a TokenParameter because the Patient.identifier parameter is a token).
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|referenceWithStaticChain}}
```
# Search Parameters: Composite
Composite search parameters incorporate two parameters in a single value. Each of those parameters will themselves have a parameter type.
In the following example, Observation.name-value-date is shown. This parameter is a composite of a string and a date. Note that the composite parameter types (StringParam and DateParam) must be specified in both the annotation's `compositeTypes` field, as well as the generic types for the `CompositeParam` method parameter itself.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|searchComposite}}
```
Example URL to invoke this method:
```url
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).
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.
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).
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.
The following example shows a method with two parameters.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|searchOptionalParam}}
```
Example URLs to invoke this method:
```url
http://fhir.example.com/Patient?family=SMITH
http://fhir.example.com/Patient?family=SMITH&given=JOHN
```
# Multi-Valued (AND/OR) Parameters
It is possible to accept multiple values of a single parameter as well. This is useful in cases when you want to return a list of resources with criteria matching a list of possible values. See the [FHIR Specification](http://www.hl7.org/implement/standards/fhir/search.html#combining) for more information.
The FHIR specification allows two types of composite parameters:
* Where a parameter may accept multiple comma separated values within a single value string (e.g.
`?language=FR,NL`) this is treated as an ***OR*** relationship, and the search should return elements matching either one or the other.
* Where a parameter may accept multiple value strings for the same parameter name (e.g. `?language=FR&language=NL`) this is treated as an ***AND*** relationship, and the search should return only elements matching both.
It is worth noting that according to the FHIR specification, you can have an AND relationship combining multiple OR relationships, but not vice-versa. In other words, it's possible to support a search like
`("name" = ("joe" or "john")) AND ("age" = (11 or 12))` but not a search like `("language" = ("en" AND "fr") OR ("address" = ("Canada" AND "Quebec"))`. If you wish to support the latter, you may consider implementing the [_filter parameter](#filter).
## 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.
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).
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):
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|searchMultiple}}
```
Example URL to invoke this method:
```url
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).
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:
```url
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.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|searchMultipleAnd}}
```
Note that AND parameters join multiple OR parameters together, but the inverse is not true. In other words, it is possible in FHIR to use AND search parameters to specify a search criteria of `(A=1 OR A=2) AND (B=1 OR B=2)` but it is not possible to specify `(A=1 AND B=1) OR (A=2 AND B=2)` (aside from
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).
# Resource Includes (_include)
FHIR allows clients to request that specific linked resources be included as contained resources, which means that they will be "embedded" in a special container called "contained" within the parent resource.
HAPI allows you to add a parameter for accepting includes if you wish to support them for specific search methods.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|pathSpec}}
```
Example URL to invoke this method:
```url
http://fhir.example.com/DiagnosticReport?identifier=7000135&_include=DiagnosticReport.subject
```
It is also possible to use a String type for the include parameter, which is more convenient if only a single include (or null for none) is all that is required.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|pathSpecSimple}}
```
# 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.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|revInclude}}
```
# Named Queries (_query)
FHIR supports [named queries](http://www.hl7.org/implement/standards/fhir/search.html#advanced), which may have specific behaviour defined. The following example shows how to create a Search operation with a name.
This operation can only be invoked by explicitly specifying the given query name in the request URL. Note that the query does not need to take any parameters.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|searchNamedQuery}}
```
Example URL to invoke this method:
```url
http://fhir.example.com/Patient?_query=namedQuery1&someparam=value
```
# Sorting (_sort)
FHIR supports [sorting](http://www.hl7.org/implement/standards/fhir/search.html#sort) according to a specific set of rules.
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:
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|sort}}
```
Example URL to invoke this method:
```url
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.
```java
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|searchWithDocs}}
```

View File

@ -0,0 +1,41 @@
# HAPI FHIR Server Introduction
HAPI FHIR provides several mechanisms for building FHIR servers. The appropriate choice depends on the specifics of what you are trying to accomplish.
## Plain Server / Facade
The HAPI FHIR Plain Server (often referred to as a Facade) is an implementation of a FHIR server against an arbitrary backend that you provide.
In this mode, you write code that handles resource storage and retrieval logic, and HAPI FHIR takes care of:
* HTTP Processing
* Parsing / Serialization
* FHIR REST semantics
This module was originally created at [University Health Network](https://uhn.ca) (UHN) as a mechanism for placing a common FHIR layer on top of a series of existing data sources, including an EMR, an enterprise patient scheduling system, and a series of clinical data repositories. All of these systems existed long before FHIR was adoped at UHN and HAPI FHIR was created to make the process of adoping FHIR easier.
This module has been used by many organizations to successfully create FHIR servers in a variety of use cases, including:
* **Hospitals:** Adding a FHIR data access layer to Existing Enterprise Data Warehouses and Clinical Data Repositories
* **Vendors:** Integration into existing products in order to add FHIR capabilities
* **Researchers:** Aggregate data collection and reporting platforms
To get started with the Plain Server, jump to [Plain Server Introduction](./introduction.html).
## JPA Server
The HAPI FHIR JPA Server is a complete implementation of a FHIR server against a relational database. Unlike the Plain Server, the JPA server provides its own database schema and handles all storage and retrieval logic without any coding being required.
The JPA server has been successfully used in many use cases, including:
* **App Developers:** The JPA server has been used as a backend data storage layer for various mobile and web-based apps. The ease of development combined with the power of the FHIR specification makes developing clinical apps a very enjoyable experience.
* **Government/Enterprise:** Many large architectures, including enterprise messaging systems, regional data repositories, telehealth solutions, etc. have been created using HAPI FHIR JPA server as a backend. These systems often scale to handle millions of patients and beyond.
To get started with the JPA Server, jump to [JPA Server Introduction](/docs/server_jpa/introduction.html).
## JAX-RS Server
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).

View File

@ -33,22 +33,20 @@ public interface IPagingProvider {
int getMaximumPageSize();
/**
* Retrieve a result list by ID
* <p>
* Note that the <code>theRequest</code> parameter was added to this
* Retrieve a result list by Search ID
*
* @since 4.0.0 - Note that the <code>theRequest</code> parameter was added to this
* method in HAPI FHIR 4.0.0. Existing implementations may choose to
* add this parameter and not use it if needed.
* </p>
*/
IBundleProvider retrieveResultList(@Nullable RequestDetails theRequestDetails, @Nonnull String theSearchId);
/**
* Retrieve a result list by ID
* <p>
* Note that the <code>theRequest</code> parameter was added to this
* Retrieve a result list by Search ID and Page ID
*
* @since 4.0.0 - Note that the <code>theRequest</code> parameter was added to this
* method in HAPI FHIR 4.0.0. Existing implementations may choose to
* add this parameter and not use it if needed.
* </p>
*/
default IBundleProvider retrieveResultList(@Nullable RequestDetails theRequestDetails, @Nonnull String theSearchId, String thePageId) {
return null;

View File

@ -31,6 +31,13 @@
<artifactId>org.hl7.fhir.r4</artifactId>
<version>${fhir_core_version}</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.r4</artifactId>
<classifier>javadoc</classifier>
<scope>provided</scope>
<version>${fhir_core_version}</version>
</dependency>
<dependency>
<groupId>org.fhir</groupId>
<artifactId>ucum</artifactId>

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 is migrated -->
<properties>
<title>RESTful Operations</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>

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">
<!-- Content has been migrated -->
<properties>
<title>RESTful Server</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>

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 is migrated -->
<properties>
<title>Server Security</title>
</properties>