Merge branch 'master' of github.com:jamesagnew/hapi-fhir

This commit is contained in:
James Agnew 2016-02-08 14:22:20 -05:00
commit 961cde41bd
14 changed files with 292 additions and 83 deletions

View File

@ -422,7 +422,9 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
// returns a bundle
} else if (Collection.class.isAssignableFrom(returnTypeFromMethod)) {
returnTypeFromMethod = ReflectionUtil.getGenericCollectionTypeOfMethodReturnType(theMethod);
if (!verifyIsValidResourceReturnType(returnTypeFromMethod) && !isResourceInterface(returnTypeFromMethod)) {
if (returnTypeFromMethod == null) {
ourLog.trace("Method {} returns a non-typed list, can't verify return type", theMethod);
} else if (!verifyIsValidResourceReturnType(returnTypeFromMethod) && !isResourceInterface(returnTypeFromMethod)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName()
+ " returns a collection with generic type " + toLogString(returnTypeFromMethod)
+ " - Must return a resource type or a collection (List, Set) with a resource type parameter (e.g. List<Patient> or List<IBaseResource> )");

View File

@ -157,7 +157,6 @@
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<version>${phloc_schematron_version}</version>
</dependency>
</dependencies>

View File

@ -0,0 +1,122 @@
package ca.uhn.fhir.rest.server;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.param.DateAndListParam;
import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.util.PortUtil;
public class SearchWithGenericListDstu2Test {
private static CloseableHttpClient ourClient;
private static FhirContext ourCtx = FhirContext.forDstu2();
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchWithGenericListDstu2Test.class);
private static int ourPort;
private static Server ourServer;
private static String ourLastMethod;
@Before
public void before() {
ourLastMethod = null;
}
/**
* See #291
*/
@Test
public void testSearch() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?identifier=foo");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info(responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertEquals("searchByIdentifier", ourLastMethod);
assertThat(responseContent, containsString("<family value=\"FAMILY\""));
}
@AfterClass
public static void afterClass() throws Exception {
ourServer.stop();
}
@BeforeClass
public static void beforeClass() throws Exception {
ourPort = PortUtil.findFreePort();
ourServer = new Server(ourPort);
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
ServletHandler proxyHandler = new ServletHandler();
RestfulServer servlet = new RestfulServer(ourCtx);
servlet.setPagingProvider(new FifoMemoryPagingProvider(10));
servlet.setResourceProviders(patientProvider);
ServletHolder servletHolder = new ServletHolder(servlet);
proxyHandler.addServletWithMapping(servletHolder, "/*");
ourServer.setHandler(proxyHandler);
ourServer.start();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setConnectionManager(connectionManager);
ourClient = builder.build();
}
public static class DummyPatientResourceProvider implements IResourceProvider {
@Override
public Class<? extends IResource> getResourceType() {
return Patient.class;
}
//@formatter:off
@SuppressWarnings("rawtypes")
@Search()
public List searchByIdentifier(
@RequiredParam(name=Patient.SP_IDENTIFIER) TokenParam theIdentifier) {
ourLastMethod = "searchByIdentifier";
ArrayList<Patient> retVal = new ArrayList<Patient>();
retVal.add((Patient) new Patient().addName(new HumanNameDt().addFamily("FAMILY")).setId("1"));
return retVal;
}
//@formatter:on
}
}

View File

@ -771,11 +771,6 @@
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.10</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.7</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
@ -1418,7 +1413,7 @@
<module>hapi-fhir-base</module>
<module>hapi-fhir-structures-dstu</module>
<module>hapi-fhir-structures-dstu2</module>
<module>hapi-fhir-structures-hl7org-dstu2</module>
<module>hapi-fhir-structures-dstu3</module>
<module>hapi-fhir-jpaserver-base</module>
<module>hapi-fhir-jaxrsserver-base</module>
<!-- <module>hapi-fhir-cobertura</module> -->

View File

@ -6,7 +6,15 @@
<title>HAPI FHIR Changelog</title>
</properties>
<body>
<release version="1.4" date="TBD">
<release version="1.5" date="TBD">
<action type="fix" issue="291">
Fix a failure starting the REST server if a method returns an untyped List, which
among other things prevented resource provider added to the server
as CDI beans in a JBoss enviroment. Thanks to GitHub user fw060 (Fei) for
reporting and figuring out exactly why this wasn't working!
</action>
</release>
<release version="1.4" date="2016-02-04">
<action type="add">
Bump the version of a few dependencies to the
latest versions (dependent HAPI modules listed in brackets):

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -102,6 +102,7 @@
<item name="CORS Support" href="./doc_cors.html" />
<item name="Interceptors (server)" href="./doc_rest_server_interceptor.html" />
<item name="Web Testing UI" href="./doc_server_tester.html" />
<item name="JAX-RS Support" href="./doc_rest_server_jaxrs.html" />
</item>
<item name="Logging" href="./doc_logging.html" />
<item name="ETags" href="./doc_rest_etag.html" />

View File

@ -25,7 +25,7 @@
in the <code>hapi-fhir-structures-dstu3-[version].jar</code>
library, with the associated Schemas, ValueSets, and other
textual resources being found in
<code>hapi-fhir-validation-resources-[version].jar</code>.
<code>hapi-fhir-validation-resources-dstu3-[version].jar</code>.
For information on where to find these libraries, see the
<a href="./downloads.html">Downloads</a> page.
</p>
@ -73,7 +73,7 @@
<p>
A new interface has been added which serves as a master interface
for all resource classes: <code>org.hl7.fhir.instance.model.api.IBaseResource</code>.
All RI resource classes will be in the package <code>org.hl7.fhir.instance.model</code>,
All RI resource classes will be in the package <code>org.hl7.fhir.dstu3.model</code>,
as shown below.
</p>
<img src="./images/hapi-1.1-structs-resource.svg" alt="Structures"/>

View File

@ -79,7 +79,7 @@
<section name="Server Side ETags">
<p>
As of HAPI 0.9, ETag support is automatically enabled in the RESTful server.
ETag support is automatically enabled in the RESTful server.
This has the following effects:
</p>
<ul>

View File

@ -598,75 +598,6 @@
</section>
<section name="JAX-RS Server">
<p>
The standard server is implemented using Servlet technology. A <a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jaxrsserver-base">module</a>
exists which implements the server using <a href="https://jax-rs-spec.java.net/nonav/2.0/apidocs/index.html">JAX-RS</a> technology.
This enables the usage of existing Java EE interceptors and annotations. This module does not provide the full set of features.
The server currently supports
<a href="./doc_rest_server.html#ConformanceMetadata_Statement">Conformance Statements</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Read.html">@Read</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Search.html">@Search</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Create.html">@Create</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Update.html">@Update</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Delete.html">@Delete</a> and
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Operation.html">@Operation</a>.
</p>
<p>
The primary intention for this project is to ensure that other web technologies (JAX-RS in this case) can be used together with the base-server functionality.
An example server can be found in the Git repo <a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jaxrsserver-example">here</a>.
</p>
<subsection name="JAX-RS Implementation specifics">
<p>
The set-up of a JAX-RS server goes beyond the scope of this documentation. The implementation of the server follows the same pattern as the standard server. It is required
to put the correct <a href="./doc_rest_operations.html">annotation</a> on the methods in the <a href="#Defining_Resource_Providers">Resource Providers</a> in order to be able to call them.
</p>
<p>
Implementing a JAX-RS Resource Provider requires some JAX-RS annotations. The <code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/Path.html">@Path</a></code>
annotation needs to define the resource path. The <code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/Produces.html">@Produces</a></code> annotation
needs to declare the produced formats. The constructor needs to pass the class of the object explicitely in order to avoid problems with proxy classes in a Java EE environment.
It is necessary to extend the abstract class
<code><a href="http://jamesagnew.github.io/hapi-fhir/apidocs/ca/uhn/fhir/jaxrs/server/AbstractJaxRsResourceProvider.html">AbstractJaxRsResourceProvider</a></code>.
<macro name="snippet">
<param name="id" value="jax-rs-provider-construction" />
<param name="file" value="examples/src/main/java/example/JaxRsPatientRestProvider.java" />
</macro>
</p>
<p>
<a href="./doc_rest_operations.html#Extended_Operations">Extended Operations</a> require the correct JAX-RS (
<code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/Path.html">@Path</a></code>,
<code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/GET.html">@GET</a></code> or
<code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/POST.html">@POST</a></code>) annotations. The body of the method needs to call the
method <code><a href="http://jamesagnew.github.io/hapi-fhir/apidocs/ca/uhn/fhir/jaxrs/server/AbstractJaxRsResourceProvider.html#customOperation-java.lang.String-ca.uhn.fhir.rest.api.RequestTypeEnum-java.lang.String-java.lang.String-ca.uhn.fhir.rest.api.RestOperationTypeEnum">AbstractJaxRsResourceProvider#customOperation</a></code>
with the correct parameters. The server will then call the method with corresponding name.
<macro name="snippet">
<param name="id" value="jax-rs-provider-operation" />
<param name="file" value="examples/src/main/java/example/JaxRsPatientRestProvider.java" />
</macro>
</p>
<p>
In order to create the conformance profile, a conformance provider class needs to be deployed which exports the provider's conformance statements.
These providers need to be returned as the result of
the method <code><a href="http://jamesagnew.github.io/hapi-fhir/apidocs/ca/uhn/fhir/jaxrs/server/AbstractJaxRsResourceProvider.html#getProviders">AbstractJaxRsResourceProvider#getProviders</a></code>.
This method is called once, during <code><a href="https://docs.oracle.com/javaee/6/api/javax/annotation/PostConstruct.html">PostConstruct</a></code>.
<macro name="snippet">
<param name="id" value="jax-rs-conformance" />
<param name="file" value="examples/src/main/java/example/JaxRsConformanceProvider.java" />
</macro>
</p>
</subsection>
</section>
</body>
</document>

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<properties>
<title>JAX-RS Server</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<section name="JAX-RS Server">
<p>
The standard server is implemented using Servlet technology. A <a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jaxrsserver-base">module</a>
exists which implements the server using <a href="https://jax-rs-spec.java.net/nonav/2.0/apidocs/index.html">JAX-RS</a> technology.
This enables the usage of existing Java EE interceptors and annotations. This module does not provide the full set of features.
The server currently supports
<a href="./doc_rest_server.html#ConformanceMetadata_Statement">Conformance Statements</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Read.html">@Read</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Search.html">@Search</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Create.html">@Create</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Update.html">@Update</a>,
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Delete.html">@Delete</a> and
<a href="./apidocs/ca/uhn/fhir/rest/annotation/Operation.html">@Operation</a>.
</p>
<p>
The primary intention for this project is to ensure that other web technologies (JAX-RS in this case) can be used together with the base-server functionality.
An example server can be found in the Git repo <a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jaxrsserver-example">here</a>.
</p>
<subsection name="JAX-RS Implementation specifics">
<p>
The set-up of a JAX-RS server goes beyond the scope of this documentation. The implementation of the server follows the same pattern as the standard server. It is required
to put the correct <a href="./doc_rest_operations.html">annotation</a> on the methods in the <a href="#Defining_Resource_Providers">Resource Providers</a> in order to be able to call them.
</p>
<p>
Implementing a JAX-RS Resource Provider requires some JAX-RS annotations. The <code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/Path.html">@Path</a></code>
annotation needs to define the resource path. The <code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/Produces.html">@Produces</a></code> annotation
needs to declare the produced formats. The constructor needs to pass the class of the object explicitely in order to avoid problems with proxy classes in a Java EE environment.
It is necessary to extend the abstract class
<code><a href="http://jamesagnew.github.io/hapi-fhir/apidocs/ca/uhn/fhir/jaxrs/server/AbstractJaxRsResourceProvider.html">AbstractJaxRsResourceProvider</a></code>.
<macro name="snippet">
<param name="id" value="jax-rs-provider-construction" />
<param name="file" value="examples/src/main/java/example/JaxRsPatientRestProvider.java" />
</macro>
</p>
<p>
<a href="./doc_rest_operations.html#Extended_Operations">Extended Operations</a> require the correct JAX-RS (
<code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/Path.html">@Path</a></code>,
<code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/GET.html">@GET</a></code> or
<code><a href="https://docs.oracle.com/javaee/6/api/javax/ws/rs/POST.html">@POST</a></code>) annotations. The body of the method needs to call the
method <code><a href="http://jamesagnew.github.io/hapi-fhir/apidocs/ca/uhn/fhir/jaxrs/server/AbstractJaxRsResourceProvider.html#customOperation-java.lang.String-ca.uhn.fhir.rest.api.RequestTypeEnum-java.lang.String-java.lang.String-ca.uhn.fhir.rest.api.RestOperationTypeEnum">AbstractJaxRsResourceProvider#customOperation</a></code>
with the correct parameters. The server will then call the method with corresponding name.
<macro name="snippet">
<param name="id" value="jax-rs-provider-operation" />
<param name="file" value="examples/src/main/java/example/JaxRsPatientRestProvider.java" />
</macro>
</p>
<p>
In order to create the conformance profile, a conformance provider class needs to be deployed which exports the provider's conformance statements.
These providers need to be returned as the result of
the method <code><a href="http://jamesagnew.github.io/hapi-fhir/apidocs/ca/uhn/fhir/jaxrs/server/AbstractJaxRsResourceProvider.html#getProviders">AbstractJaxRsResourceProvider#getProviders</a></code>.
This method is called once, during <code><a href="https://docs.oracle.com/javaee/6/api/javax/annotation/PostConstruct.html">PostConstruct</a></code>.
<macro name="snippet">
<param name="id" value="jax-rs-conformance" />
<param name="file" value="examples/src/main/java/example/JaxRsConformanceProvider.java" />
</macro>
</p>
</subsection>
</section>
<section name="A Complete Example">
<p>
A complete example showing how to implement a JAX-RS RESTful server can
be found in our Git repo here:
<a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jaxrsserver-example">https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jaxrsserver-example</a>
</p>
</section>
</body>
</document>

View File

@ -46,6 +46,7 @@
<li><a href="./doc_cors.html">CORS Support</a></li>
<li><a href="./doc_rest_server_interceptor.html">Interceptors (server)</a></li>
<li><a href="./doc_server_tester.html">Web Testing UI</a></li>
<li><a href="./doc_rest_server_jaxrs.html">JAX-RS Support</a></li>
</ul>
<h4>Other Features</h4>

View File

@ -60,6 +60,66 @@
</section>
<section name="Announcements">
<p>
<b>February 4, 2016 - HAPI FHIR 1.4 Released</b> -
The next release of HAPI has now been uploaded to the Maven repos and
GitHub's releases section.
</p>
<p>
This release has taken a lot longer than originally planned. Mainly this
is because we have taken a number of huge steps towards integrating
HAPI FHIR with the HL7.org Java Reference Implementation. This
effort will mean great things for all Java FHIR developers from now
on, as it will bring a rich set of tools to everyone. See the
<a href="./doc_dstu2.html">DSTU3/RI page</a> for information on
this effort.
</p>
<p>
This release brings a number of bugfixes and a few bigger things.
As always, the <a href="./changes-report.html">changelog</a> has the full list
of changes in this version. Some changes of note include:
</p>
<ul>
<li>
This release adds support for the current draft DSTU3 structure definitions,
which were called DSTU2.1 until the decision in January by HL7 to call the
next release DSTU3. See the
<a href="./downloads.html">downloads page</a> for information on the
various versions of FHIR supported by HAPI FHIR.
</li>
<li>
Two great new modules to HAPI FHIR have been contributed to the
project! A huge thanks to both contributors for their ongoing
efforts.
<li>
A new OSGi module (<a href="http://search.maven.org/#search|gav|1|g%3A%22ca.uhn.hapi.fhir%22%20AND%20a%3A%22hapi-fhir-osgi-core%22">hapi-fhir-osgi-core</a>) has been contributed
by
<a href="https://www.akana.com/">Akana</a>. This module was originally added in the 1.3 release cycle but
was cleaned up for use in 1.4.
</li>
<li>
A new adapter
(<a href="./doc_rest_server_jaxrs.html">hapi-fhir-jaxrsserver-base</a>)
which allows the RESTful server to be used in JAX-RS environment
was contributed by <a href="http://www.agfahealthcare.com/">AGFA Healthcare</a>.
</li>
</li>
<li>
The Command-Line tool (<a href="./doc_cli.html">hapi-fhir-cli</a>) has been
given options to start the server and uploader tools in either DSTU2
or DSTU3 mode. Both are supported by the same tool installation.
</li>
<li>
Several of HAPI's library dependencies have been upgraded to the latest version
(see the first entry in the <a href="./changes-report.html">changelog</a>)
</li>
</ul>
<p>
And just a reminder, if you haven't yet filled out the
<a href="http://goo.gl/forms/R8Ifg2qvOY">HAPI FHIR Community Survey</a>, we
would really appreciate if you did so!
</p>
<!--
<p>
<b>November 15, 2015 - HAPI FHIR 1.3 Released</b> -
The next release of HAPI has now been uploaded to the Maven repos and
@ -101,6 +161,7 @@
<a href="http://goo.gl/forms/R8Ifg2qvOY">HAPI FHIR Community Survey</a>, we
would really appreciate if you did so!
</p>
-->
<!--
<p>
<b>September 18, 2015 - HAPI FHIR 1.2 and Community Survey</b> -