add server using jaxrs
This commit is contained in:
parent
9664174b6a
commit
b4df6f9612
|
@ -0,0 +1,5 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
public interface IRestfulHeader {
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
public interface IRestfulServer {
|
||||
|
||||
/**
|
||||
* Gets the {@link FhirContext} associated with this server. For efficient processing, resource providers and plain providers should generally use this context if one is needed, as opposed to
|
||||
* creating their own.
|
||||
*/
|
||||
public FhirContext getFhirContext();
|
||||
|
||||
public List<IServerInterceptor> getInterceptors();
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
public interface IRestfulServerDefaults {
|
||||
|
||||
/**
|
||||
* Should the server "pretty print" responses by default (requesting clients can always override this default by supplying an <code>Accept</code> header in the request, or a <code>_pretty</code>
|
||||
* parameter in the request URL.
|
||||
* <p>
|
||||
* The default is <code>false</code>
|
||||
* </p>
|
||||
*
|
||||
* @return Returns the default pretty print setting
|
||||
*/
|
||||
public boolean isDefaultPrettyPrint();
|
||||
|
||||
}
|
|
@ -41,7 +41,6 @@ import java.util.concurrent.locks.Lock;
|
|||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.UnavailableException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -76,7 +75,7 @@ import ca.uhn.fhir.util.ReflectionUtil;
|
|||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import ca.uhn.fhir.util.VersionUtil;
|
||||
|
||||
public class RestfulServer extends HttpServlet {
|
||||
public class RestfulServer extends HttpServlet implements IRestfulServerDefaults, IRestfulServer {
|
||||
|
||||
private static final ExceptionHandlingInterceptor DEFAULT_EXCEPTION_HANDLER = new ExceptionHandlingInterceptor();
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -1086,6 +1085,7 @@ public class RestfulServer extends HttpServlet {
|
|||
*
|
||||
* @return Returns the default pretty print setting
|
||||
*/
|
||||
@Override
|
||||
public boolean isDefaultPrettyPrint() {
|
||||
return myDefaultPrettyPrint;
|
||||
}
|
||||
|
|
|
@ -510,7 +510,7 @@ public class RestfulServerUtils {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static boolean prettyPrintResponse(RestfulServer theServer, RequestDetails theRequest) {
|
||||
public static boolean prettyPrintResponse(IRestfulServerDefaults theServer, RequestDetails theRequest) {
|
||||
Map<String, String[]> requestParams = theRequest.getParameters();
|
||||
String[] pretty = requestParams.get(Constants.PARAM_PRETTY);
|
||||
boolean prettyPrint;
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
|
||||
public class RestulfulServerConfiguration {
|
||||
|
||||
private List<ResourceBinding> resourceBindings;
|
||||
private List<BaseMethodBinding<?>> serverBindings;
|
||||
private String implementationDescription;
|
||||
private String serverVersion;
|
||||
private String serverName;
|
||||
private FhirContext fhirContext;
|
||||
private ServletContext servletContext;
|
||||
private IServerAddressStrategy serverAddressStrategy;
|
||||
private String conformanceDate;
|
||||
|
||||
public RestulfulServerConfiguration() {
|
||||
}
|
||||
|
||||
public RestulfulServerConfiguration(RestfulServer theRestfulServer) {
|
||||
this.resourceBindings = new LinkedList<ResourceBinding>(theRestfulServer.getResourceBindings());
|
||||
this.serverBindings = theRestfulServer.getServerBindings();
|
||||
this.implementationDescription = theRestfulServer.getImplementationDescription();
|
||||
this.serverVersion = theRestfulServer.getServerVersion();
|
||||
this.serverName = theRestfulServer.getServerName();
|
||||
this.fhirContext = theRestfulServer.getFhirContext();
|
||||
this.serverAddressStrategy= theRestfulServer.getServerAddressStrategy();
|
||||
this.servletContext = theRestfulServer.getServletContext();
|
||||
if (servletContext != null) {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = getServletContext().getResourceAsStream("/META-INF/MANIFEST.MF");
|
||||
if (inputStream != null) {
|
||||
Manifest manifest = new Manifest(inputStream);
|
||||
this.conformanceDate = manifest.getMainAttributes().getValue("Build-Time");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// fall through
|
||||
}
|
||||
finally {
|
||||
if (inputStream != null) {
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the resourceBindings
|
||||
* @return the resourceBindings
|
||||
*/
|
||||
public List<ResourceBinding> getResourceBindings() {
|
||||
return resourceBindings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the resourceBindings
|
||||
* @param resourceBindings the resourceBindings to set
|
||||
*/
|
||||
public RestulfulServerConfiguration setResourceBindings(List<ResourceBinding> resourceBindings) {
|
||||
this.resourceBindings = resourceBindings;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the serverBindings
|
||||
* @return the serverBindings
|
||||
*/
|
||||
public List<BaseMethodBinding<?>> getServerBindings() {
|
||||
return serverBindings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the serverBindings
|
||||
* @param serverBindings the serverBindings to set
|
||||
*/
|
||||
public RestulfulServerConfiguration setServerBindings(List<BaseMethodBinding<?>> serverBindings) {
|
||||
this.serverBindings = serverBindings;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the implementationDescription
|
||||
* @return the implementationDescription
|
||||
*/
|
||||
public String getImplementationDescription() {
|
||||
return implementationDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the implementationDescription
|
||||
* @param implementationDescription the implementationDescription to set
|
||||
*/
|
||||
public RestulfulServerConfiguration setImplementationDescription(String implementationDescription) {
|
||||
this.implementationDescription = implementationDescription;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the serverVersion
|
||||
* @return the serverVersion
|
||||
*/
|
||||
public String getServerVersion() {
|
||||
return serverVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the serverVersion
|
||||
* @param serverVersion the serverVersion to set
|
||||
*/
|
||||
public RestulfulServerConfiguration setServerVersion(String serverVersion) {
|
||||
this.serverVersion = serverVersion;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the serverName
|
||||
* @return the serverName
|
||||
*/
|
||||
public String getServerName() {
|
||||
return serverName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the serverName
|
||||
* @param serverName the serverName to set
|
||||
*/
|
||||
public RestulfulServerConfiguration setServerName(String serverName) {
|
||||
this.serverName = serverName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the servletContext
|
||||
* @return the servletContext
|
||||
*/
|
||||
public ServletContext getServletContext() {
|
||||
return servletContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the servletContext
|
||||
* @param servletContext the servletContext to set
|
||||
*/
|
||||
public RestulfulServerConfiguration setServletContext(ServletContext servletContext) {
|
||||
this.servletContext = servletContext;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link FhirContext} associated with this server. For efficient processing, resource providers and plain providers should generally use this context if one is needed, as opposed to
|
||||
* creating their own.
|
||||
*/
|
||||
public FhirContext getFhirContext() {
|
||||
return this.fhirContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fhirContext
|
||||
* @param fhirContext the fhirContext to set
|
||||
*/
|
||||
public RestulfulServerConfiguration setFhirContext(FhirContext fhirContext) {
|
||||
this.fhirContext = fhirContext;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the serverAddressStrategy
|
||||
* @return the serverAddressStrategy
|
||||
*/
|
||||
public IServerAddressStrategy getServerAddressStrategy() {
|
||||
return serverAddressStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the serverAddressStrategy
|
||||
* @param serverAddressStrategy the serverAddressStrategy to set
|
||||
*/
|
||||
public void setServerAddressStrategy(IServerAddressStrategy serverAddressStrategy) {
|
||||
this.serverAddressStrategy = serverAddressStrategy;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the conformanceDate
|
||||
* @return the conformanceDate
|
||||
*/
|
||||
public String getConformanceDate() {
|
||||
return conformanceDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the conformanceDate
|
||||
* @param conformanceDate the conformanceDate to set
|
||||
*/
|
||||
public void setConformanceDate(String conformanceDate) {
|
||||
this.conformanceDate = conformanceDate;
|
||||
}
|
||||
|
||||
public String getServerBaseForRequest(HttpServletRequest theRequest) {
|
||||
return getServerAddressStrategy().determineServerBase(getServletContext(), theRequest);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,274 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>maven.java.net</id>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
<url>https://maven.java.net/service/local/repositories/snapshots/content/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<artifactId>hapi-fhir-jaxrsserver-base</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HAPI FHIR JAX-RS Server</name>
|
||||
|
||||
<dependencies>
|
||||
<!-- HAPI DEPENDENCIES -->
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- UNKNOWN -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.phloc</groupId>
|
||||
<artifactId>phloc-schematron</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.phloc</groupId>
|
||||
<artifactId>phloc-commons</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- PREVIOUS TESTING
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlets</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlet</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
-->
|
||||
<!-- own api -->
|
||||
<!--dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<version>2.2.1.GA</version>
|
||||
<scope>test</scope>
|
||||
</dependency-->
|
||||
<dependency>
|
||||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>jsr311-api</artifactId>
|
||||
<version>1.1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.ejb</groupId>
|
||||
<artifactId>ejb-api</artifactId>
|
||||
<version>3.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<!-- Jetty -->
|
||||
<!-- http://stackoverflow.com/questions/10048004/integrating-jetty-with-jax-rs-jersey -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Jersey (JAX-RS) -->
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-server</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey.contribs</groupId>
|
||||
<artifactId>jersey-spring</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>jsr311-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-test-framework</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.grizzly</groupId>
|
||||
<artifactId>grizzly-servlet-webserver</artifactId>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<!--
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipDeploy>true</skipDeploy>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-tinder-plugin</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>build_dstu1</id>
|
||||
<goals>
|
||||
<goal>generate-jparest-server</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<version>dstu</version>
|
||||
<packageBase>ca.uhn.fhir.jpa.rp.dstu</packageBase>
|
||||
<targetResourceSpringBeansFile>hapi-fhir-server-resourceproviders-dstu1.xml</targetResourceSpringBeansFile>
|
||||
<baseResourceNames/>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>build_dstu2</id>
|
||||
<goals>
|
||||
<goal>generate-jparest-server</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<version>dstu2</version>
|
||||
<packageBase>ca.uhn.fhir.jpa.rp.dstu2</packageBase>
|
||||
<targetResourceSpringBeansFile>hapi-fhir-server-resourceproviders-dstu2.xml</targetResourceSpringBeansFile>
|
||||
<baseResourceNames/>
|
||||
<excludeResourceNames>
|
||||
<excludeResourceName>OperationDefinition</excludeResourceName>
|
||||
<excludeResourceName>OperationOutcome</excludeResourceName>
|
||||
</excludeResourceNames>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${basedir}/src/main/resources</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>${basedir}/target/generated-sources/tinder</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>${basedir}/target/generated-resources/tinder</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
-->
|
||||
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jxr-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,152 @@
|
|||
package ca.uhn.fhir.jaxrs.server;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.OPTIONS;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.ResponseBuilder;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Conformance;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
|
||||
import ca.uhn.fhir.rest.server.ResourceBinding;
|
||||
import ca.uhn.fhir.rest.server.RestulfulServerConfiguration;
|
||||
import ca.uhn.fhir.rest.server.provider.dstu2.ServerConformanceProvider;
|
||||
import ca.uhn.fhir.util.ReflectionUtil;
|
||||
|
||||
/**
|
||||
* Conformance Rest Service
|
||||
* @author Peter Van Houte
|
||||
*/
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public abstract class AbstractConformanceRestServer extends AbstractJaxRsRestServer implements IConformanceRestServer {
|
||||
|
||||
public static final String PATH = "/";
|
||||
private static final org.slf4j.Logger ourLog = LoggerFactory.getLogger(AbstractConformanceRestServer.class);
|
||||
|
||||
private ResourceBinding myServerBinding = new ResourceBinding();
|
||||
private ConcurrentHashMap<String, ResourceBinding> myResourceNameToBinding = new ConcurrentHashMap<String, ResourceBinding>();
|
||||
private RestulfulServerConfiguration serverConfiguration = new RestulfulServerConfiguration();
|
||||
|
||||
private Conformance myConformance;
|
||||
|
||||
protected AbstractConformanceRestServer(String implementationDescription, String serverName, String serverVersion) {
|
||||
serverConfiguration.setFhirContext(getFhirContext());
|
||||
serverConfiguration.setImplementationDescription(implementationDescription);
|
||||
serverConfiguration.setServerName(serverName);
|
||||
serverConfiguration.setServerVersion(serverVersion);
|
||||
}
|
||||
|
||||
protected void setUpPostConstruct()
|
||||
throws Exception {
|
||||
List<BaseMethodBinding<?>> serverBindings = new ArrayList<BaseMethodBinding<?>>();
|
||||
for (ResourceBinding baseMethodBinding : myResourceNameToBinding.values()) {
|
||||
serverBindings.addAll(baseMethodBinding.getMethodBindings());
|
||||
}
|
||||
serverConfiguration.setServerBindings(serverBindings);
|
||||
serverConfiguration.setResourceBindings(new LinkedList<ResourceBinding>(myResourceNameToBinding.values()));
|
||||
HardcodedServerAddressStrategy hardcodedServerAddressStrategy = new HardcodedServerAddressStrategy();
|
||||
hardcodedServerAddressStrategy.setValue(getBaseUri());
|
||||
serverConfiguration.setServerAddressStrategy(hardcodedServerAddressStrategy);
|
||||
ServerConformanceProvider serverConformanceProvider = new ServerConformanceProvider(serverConfiguration);
|
||||
serverConformanceProvider.initializeOperations();
|
||||
myConformance = serverConformanceProvider.getServerConformance(null);
|
||||
}
|
||||
|
||||
@GET
|
||||
@OPTIONS
|
||||
@Path("/metadata")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response conformance(String string) {
|
||||
String conformanceString = getParser().encodeResourceToString(myConformance);
|
||||
ResponseBuilder entity = Response.status(Constants.STATUS_HTTP_200_OK).entity(conformanceString);
|
||||
entity.header("Access-Control-Allow-Origin", "*");
|
||||
return entity.build();
|
||||
}
|
||||
|
||||
protected int findResourceMethods(Object theProvider, Class<?> clazz) throws ConfigurationException {
|
||||
int count = 0;
|
||||
|
||||
for (Method m : ReflectionUtil.getDeclaredMethods(clazz)) {
|
||||
BaseMethodBinding<?> foundMethodBinding = BaseMethodBinding.bindMethod(m, getFhirContext(), theProvider);
|
||||
if (foundMethodBinding == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
// if (foundMethodBinding instanceof ConformanceMethodBinding) {
|
||||
// myServerConformanceMethod = foundMethodBinding;
|
||||
// continue;
|
||||
// }
|
||||
|
||||
if (!Modifier.isPublic(m.getModifiers())) {
|
||||
throw new ConfigurationException("Method '" + m.getName() + "' is not public, FHIR RESTful methods must be public");
|
||||
} else {
|
||||
if (Modifier.isStatic(m.getModifiers())) {
|
||||
throw new ConfigurationException("Method '" + m.getName() + "' is static, FHIR RESTful methods must not be static");
|
||||
} else {
|
||||
ourLog.debug("Scanning public method: {}#{}", theProvider.getClass(), m.getName());
|
||||
|
||||
String resourceName = foundMethodBinding.getResourceName();
|
||||
ResourceBinding resourceBinding;
|
||||
if (resourceName == null) {
|
||||
resourceBinding = myServerBinding;
|
||||
} else {
|
||||
RuntimeResourceDefinition definition = getFhirContext().getResourceDefinition(resourceName);
|
||||
if (myResourceNameToBinding.containsKey(definition.getName())) {
|
||||
resourceBinding = myResourceNameToBinding.get(definition.getName());
|
||||
} else {
|
||||
resourceBinding = new ResourceBinding();
|
||||
resourceBinding.setResourceName(resourceName);
|
||||
myResourceNameToBinding.put(resourceName, resourceBinding);
|
||||
}
|
||||
}
|
||||
|
||||
List<Class<?>> allowableParams = foundMethodBinding.getAllowableParamAnnotations();
|
||||
if (allowableParams != null) {
|
||||
for (Annotation[] nextParamAnnotations : m.getParameterAnnotations()) {
|
||||
for (Annotation annotation : nextParamAnnotations) {
|
||||
Package pack = annotation.annotationType().getPackage();
|
||||
if (pack.equals(IdParam.class.getPackage())) {
|
||||
if (!allowableParams.contains(annotation.annotationType())) {
|
||||
throw new ConfigurationException("Method[" + m.toString() + "] is not allowed to have a parameter annotated with " + annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resourceBinding.addMethod(foundMethodBinding);
|
||||
ourLog.debug(" * Method: {}#{} is a handler", theProvider.getClass(), m.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<? extends IBaseResource> getResourceType() {
|
||||
return Conformance.class;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
package ca.uhn.fhir.jaxrs.server;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
|
||||
/**
|
||||
* Abstract Jax Rs Rest Server
|
||||
* @author axmpm
|
||||
*
|
||||
*/
|
||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
public abstract class AbstractJaxRsRestServer {
|
||||
|
||||
private static Logger ourLog = LoggerFactory.getLogger(AbstractJaxRsRestServer.class);
|
||||
public static FhirContext CTX = FhirContext.forDstu2();
|
||||
|
||||
@Context
|
||||
protected UriInfo info;
|
||||
@Context
|
||||
HttpHeaders headers;
|
||||
|
||||
private IParser jsonParser = getFhirContext().newJsonParser();
|
||||
private IParser xmlParser = getFhirContext().newXmlParser();
|
||||
private String baseUri;
|
||||
|
||||
public static FhirContext getFhirContext() {
|
||||
return CTX;
|
||||
}
|
||||
|
||||
/**
|
||||
* param and query methods
|
||||
*/
|
||||
protected HashMap<String, String[]> getQueryMap() {
|
||||
MultivaluedMap<String, String> queryParameters = info.getQueryParameters();
|
||||
HashMap<String, String[]> params = new HashMap<String, String[]>();
|
||||
for (String key : queryParameters.keySet()) {
|
||||
params.put(key, queryParameters.get(key).toArray(new String[] {}));
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
private String getParam(String string) {
|
||||
for (Entry<String, List<String>> entry : info.getQueryParameters().entrySet()) {
|
||||
if (string.equalsIgnoreCase(entry.getKey())) {
|
||||
return entry.getValue().iterator().next();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Integer getIntParam(String string) {
|
||||
String param = getParam(string);
|
||||
return param == null ? 0 : Integer.valueOf(param);
|
||||
}
|
||||
|
||||
protected String getBaseUri() {
|
||||
if(this.baseUri == null) {
|
||||
this.baseUri = info.getBaseUri().toASCIIString();
|
||||
}
|
||||
ourLog.debug("BaseUri is equal to %s", baseUri);
|
||||
return this.baseUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* PARSING METHODS
|
||||
*/
|
||||
public IParser getParser() {
|
||||
IParser parser = MediaType.APPLICATION_XML.equals(getParserType()) ? xmlParser : jsonParser;
|
||||
return parser.setPrettyPrint(getPrettyPrint());
|
||||
}
|
||||
|
||||
private boolean getPrettyPrint() {
|
||||
String printPretty = getParam("_pretty");
|
||||
return printPretty == null || printPretty.trim().length() == 0 ? true : Boolean.valueOf(printPretty);
|
||||
}
|
||||
|
||||
protected String getParserType() {
|
||||
if ((headers != null && headers.getMediaType() != null && headers.getMediaType().getSubtype() != null
|
||||
&& headers.getMediaType().getSubtype().contains("xml")) || getDefaultResponseEncoding() == EncodingEnum.XML
|
||||
|| "xml".equals(getParam("_format"))) {
|
||||
return MediaType.APPLICATION_XML;
|
||||
} else {
|
||||
return MediaType.APPLICATION_JSON;
|
||||
}
|
||||
}
|
||||
|
||||
Response createResponse(IBaseResource resource) {
|
||||
Bundle resultingBundle = new Bundle();
|
||||
resultingBundle.addEntry().setResource((IResource) resource);
|
||||
return ok(encodeResponse(resultingBundle));
|
||||
}
|
||||
|
||||
protected Response ok(String entity) {
|
||||
return Response.status(Constants.STATUS_HTTP_200_OK).header("Content-Type", getParserType()).entity(entity).build();
|
||||
}
|
||||
|
||||
private String encodeResponse(Bundle resource) {
|
||||
return resource == null ? "null" : getParser().encodeBundleToString(resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* DEFAULT VALUES
|
||||
*/
|
||||
public EncodingEnum getDefaultResponseEncoding() {
|
||||
return EncodingEnum.JSON;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,230 @@
|
|||
package ca.uhn.fhir.jaxrs.server;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.interceptor.Interceptors;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ca.uhn.fhir.jaxrs.server.interceptor.ExceptionInterceptor;
|
||||
import ca.uhn.fhir.jaxrs.server.util.MethodBindings;
|
||||
import ca.uhn.fhir.jaxrs.server.util.RestfulServerDefaults;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.method.CreateMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.OperationMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.IRestfulServerDefaults;
|
||||
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
|
||||
import ca.uhn.fhir.rest.server.ResourceBinding;
|
||||
|
||||
/**
|
||||
* Fhir Physician Rest Service
|
||||
* @author axmpm
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings({ "unused"})
|
||||
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
|
||||
public abstract class AbstractResourceRestServer<R extends IResource> extends AbstractJaxRsRestServer implements IResourceProvider {
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(AbstractResourceRestServer.class);
|
||||
|
||||
private ResourceBinding myServerBinding = new ResourceBinding();
|
||||
private IRestfulServerDefaults serverDefaults = new RestfulServerDefaults();
|
||||
private MethodBindings bindings = new MethodBindings();
|
||||
|
||||
public AbstractResourceRestServer(Class<?> subclass) {
|
||||
bindings.findMethods(this, subclass, getFhirContext());
|
||||
}
|
||||
|
||||
@GET
|
||||
@Interceptors(ExceptionInterceptor.class)
|
||||
Response search() throws Exception {
|
||||
return execute();
|
||||
}
|
||||
|
||||
protected Response customOperation(final IBaseResource resource, RequestTypeEnum requestType)
|
||||
throws Exception, IllegalAccessException, InvocationTargetException {
|
||||
OperationMethodBinding method = bindings.getBinding(OperationMethodBinding.class);
|
||||
final RequestDetails theRequest = createRequestDetails(resource, requestType);
|
||||
final Object[] paramsServer = bindings.createParams(resource, method, theRequest);
|
||||
Parameters result = (Parameters) method.getMethod().invoke(this, paramsServer);
|
||||
return ok(getParser().encodeResourceToString(result));
|
||||
}
|
||||
|
||||
Response create(final Map<String, String[]> params, R resource) throws Exception {
|
||||
CreateMethodBinding method = bindings.getBinding(CreateMethodBinding.class);
|
||||
final RequestDetails theRequest = createRequestDetails(resource, null);
|
||||
final Object[] paramsServer = bindings.createParams(resource, method, theRequest);
|
||||
MethodOutcome result = (MethodOutcome) method.getMethod().invoke(this, paramsServer);
|
||||
return createResponse(result.getResource());
|
||||
}
|
||||
|
||||
@POST
|
||||
@Interceptors(ExceptionInterceptor.class)
|
||||
public Response create(final String resourceString)
|
||||
throws Exception {
|
||||
return create(getQueryMap(), parseResource(resourceString));
|
||||
}
|
||||
|
||||
@POST
|
||||
@Interceptors(ExceptionInterceptor.class)
|
||||
@Path("/_search")
|
||||
public Response searchWithPost() throws Exception {
|
||||
return search();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
@Interceptors(ExceptionInterceptor.class)
|
||||
public Response find(@PathParam("id") final String id) {
|
||||
final R resource = find(new IdDt(id));
|
||||
return createSingleResponse(resource);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("/{id}")
|
||||
@Interceptors(ExceptionInterceptor.class)
|
||||
public Response update(@PathParam("id") final String id, final String resourceString)
|
||||
throws Exception {
|
||||
final R resource = parseResource(resourceString);
|
||||
// final MethodOutcome update = update(new IdDt(resource.getId()), practitioner);
|
||||
// return createResponse(update.getResource());
|
||||
return createResponse(resource);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
@Interceptors(ExceptionInterceptor.class)
|
||||
public Response delete(@PathParam("id") final String id)
|
||||
throws Exception {
|
||||
// final MethodOutcome delete = delete(new IdDt(id));
|
||||
// return createResponse(delete.getResource());
|
||||
return null;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{id}/_history/{version}")
|
||||
@Interceptors(ExceptionInterceptor.class)
|
||||
public Response findHistory(@PathParam("id") final String id, @PathParam("version") final String version) {
|
||||
final IdDt dt = new IdDt(getBaseUri(), getResourceType().getSimpleName(), id, version);
|
||||
final R resource = findHistory(dt);
|
||||
return createSingleResponse(resource);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{id}/{compartment}")
|
||||
@Interceptors(ExceptionInterceptor.class)
|
||||
public Response findCompartment(@PathParam("id") final String id, @PathParam("compartment") final String compartment) {
|
||||
final IdDt dt = new IdDt(getBaseUri(), getResourceType().getSimpleName(), id);
|
||||
final R resource = find(new IdDt(id));
|
||||
return createResponse(resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* PARSING METHODS
|
||||
*/
|
||||
private Response createSingleResponse(final R resource) {
|
||||
return ok(getParser().encodeResourceToString(resource));
|
||||
}
|
||||
|
||||
Response createResponse(final IBaseResource resource) {
|
||||
final Bundle resultingBundle = new Bundle();
|
||||
resultingBundle.addEntry().setResource((IResource) resource);
|
||||
return ok(encodeToString(resultingBundle));
|
||||
}
|
||||
|
||||
Response createResponse(final List<R> resources) {
|
||||
final Bundle resultingBundle = new Bundle();
|
||||
for (final R resource : resources) {
|
||||
addBundleEntry(resultingBundle, resource);
|
||||
}
|
||||
return ok(encodeToString(resultingBundle));
|
||||
}
|
||||
|
||||
protected Response ok(String entity) {
|
||||
return Response.status(Constants.STATUS_HTTP_200_OK).header("Content-Type", getParserType()).entity(entity).build();
|
||||
}
|
||||
|
||||
protected String encodeToString(final Bundle resource) {
|
||||
return resource != null ? getParser().encodeBundleToString(resource) : "null";
|
||||
}
|
||||
|
||||
private R parseResource(final String resource) {
|
||||
return getParser().parseResource(getResourceType(), resource);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private void addBundleEntry(final Bundle resultingBundle, final R resource) {
|
||||
final BundleEntry entry = resultingBundle.addEntry();
|
||||
entry.setResource(resource);
|
||||
if (resource != null && resource.getId() != null) {
|
||||
entry.setId(resource.getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private RequestDetails createRequestDetails(final IBaseResource resource, RequestTypeEnum requestType) {
|
||||
final RequestDetails theRequest = new RequestDetails() {
|
||||
// @Override
|
||||
// public String getHeader(String headerIfNoneExist) {
|
||||
// List<String> requestHeader = headers.getRequestHeader(headerIfNoneExist);
|
||||
// return (requestHeader == null || requestHeader.size() == 0) ? null : requestHeader.get(0);
|
||||
// }
|
||||
};
|
||||
theRequest.setFhirServerBase(getBaseUri());
|
||||
// theRequest.setServer(this);
|
||||
theRequest.setParameters(getQueryMap());
|
||||
// theRequest.setRequestContent(resource);
|
||||
theRequest.setRequestType(requestType);
|
||||
return theRequest;
|
||||
}
|
||||
|
||||
public Response execute() {
|
||||
SearchMethodBinding method = bindings.getBinding(SearchMethodBinding.class);
|
||||
final RequestDetails theRequest = createRequestDetails(null, null);
|
||||
final Object[] paramsServer = bindings.createParams(null, method, theRequest);
|
||||
Object result = null; //method.invokeServer(null, paramsServer);
|
||||
final IBundleProvider bundle = (IBundleProvider) result;
|
||||
IVersionSpecificBundleFactory bundleFactory = getFhirContext().newBundleFactory();
|
||||
// bundleFactory.initializeBundleFromBundleProvider(this, bundle, EncodingEnum.JSON, info.getAbsolutePath().toASCIIString(),
|
||||
// info.getAbsolutePath().toASCIIString(), getPrettyPrint(), getIntParam("_getpagesoffset"), getIntParam("_count"), null,
|
||||
// BundleTypeEnum.SEARCHSET, Collections.emptySet());
|
||||
IBaseResource resource = bundleFactory.getResourceBundle();
|
||||
return ok(getParser().encodeResourceToString(resource));
|
||||
}
|
||||
|
||||
public R find(final IdDt theId) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public R findHistory(final IdDt theId) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract Class<R> getResourceType();
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package ca.uhn.fhir.jaxrs.server;
|
||||
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
|
||||
public interface IConformanceRestServer extends IResourceProvider {
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package ca.uhn.fhir.jaxrs.server;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.ejb.Stateless;
|
||||
import javax.interceptor.Interceptors;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ca.uhn.fhir.jaxrs.server.interceptor.ExceptionInterceptor;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.rest.annotation.Transaction;
|
||||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||
|
||||
/**
|
||||
* Conformance Rest Service
|
||||
* @author Peter Van Houte
|
||||
*/
|
||||
@Local
|
||||
@Path(StaticJaxRsServer.PATH)
|
||||
@Stateless
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class StaticJaxRsServer {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = LoggerFactory.getLogger(StaticJaxRsServer.class);
|
||||
static final String PATH = "/";
|
||||
|
||||
@POST
|
||||
@Path("/")
|
||||
@Interceptors(ExceptionInterceptor.class)
|
||||
public Response transaction(final String resource) {
|
||||
ourLog.debug("calling transaction method");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Transaction
|
||||
public Bundle transaction(@TransactionParam Bundle theResources) {
|
||||
ourLog.debug("transaction implemented");
|
||||
return theResources;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
package ca.uhn.fhir.jaxrs.server.interceptor;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.interceptor.AroundInvoke;
|
||||
import javax.interceptor.InvocationContext;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.ResponseBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsRestServer;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.util.OperationOutcomeUtil;
|
||||
|
||||
public class ExceptionInterceptor {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = LoggerFactory.getLogger(ExceptionInterceptor.class);
|
||||
private Class<?>[] myReturnStackTracesForExceptionTypes;
|
||||
|
||||
@Context
|
||||
private UriInfo info;
|
||||
@Context
|
||||
private HttpHeaders headers;
|
||||
|
||||
FhirContext fhirContext = AbstractJaxRsRestServer.getFhirContext();
|
||||
|
||||
@AroundInvoke
|
||||
public Object intercept(final InvocationContext ctx) throws Exception {
|
||||
try {
|
||||
if(!ourLog.isDebugEnabled() || ctx.getMethod().getName().contains("getResourceType")) {
|
||||
return ctx.proceed();
|
||||
} else {
|
||||
ourLog.debug("METHOD_CALL : " + ctx.getMethod().getName() + " [ " + Arrays.asList(ctx.getParameters()) + "] ");
|
||||
Object proceed = ctx.proceed();
|
||||
ourLog.debug("RESULT : " + proceed.toString());
|
||||
return proceed;
|
||||
}
|
||||
} catch(final Exception theException) {
|
||||
return handleException(theException);
|
||||
}
|
||||
}
|
||||
|
||||
public Response handleException(final Throwable theException)
|
||||
{
|
||||
IBaseOperationOutcome oo = null;
|
||||
int statusCode = Constants.STATUS_HTTP_500_INTERNAL_ERROR;
|
||||
|
||||
if (theException instanceof BaseServerResponseException) {
|
||||
oo = ((BaseServerResponseException) theException).getOperationOutcome();
|
||||
statusCode = ((BaseServerResponseException) theException).getStatusCode();
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate an OperationOutcome to return, unless the exception throw by the resource provider had one
|
||||
*/
|
||||
if (oo == null) {
|
||||
try {
|
||||
final RuntimeResourceDefinition ooDef = fhirContext.getResourceDefinition("OperationOutcome");
|
||||
oo = (IBaseOperationOutcome) ooDef.getImplementingClass().newInstance();
|
||||
|
||||
if (theException instanceof InternalErrorException) {
|
||||
ourLog.error("Failure during REST processing", theException);
|
||||
populateDetails(fhirContext, theException, oo);
|
||||
} else if (theException instanceof BaseServerResponseException) {
|
||||
ourLog.warn("Failure during REST processing: {}", theException);
|
||||
final BaseServerResponseException baseServerResponseException = (BaseServerResponseException) theException;
|
||||
statusCode = baseServerResponseException.getStatusCode();
|
||||
populateDetails(fhirContext, theException, oo);
|
||||
if (baseServerResponseException.getAdditionalMessages() != null) {
|
||||
for (final String next : baseServerResponseException.getAdditionalMessages()) {
|
||||
OperationOutcomeUtil.addIssue(fhirContext, oo, "error", next);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ourLog.error("Failure during REST processing: " + theException.toString(), theException);
|
||||
populateDetails(fhirContext, theException, oo);
|
||||
statusCode = Constants.STATUS_HTTP_500_INTERNAL_ERROR;
|
||||
}
|
||||
} catch (final Exception e1) {
|
||||
ourLog.error("Failed to instantiate OperationOutcome resource instance", e1);
|
||||
final ResponseBuilder result = Response.status(Constants.STATUS_HTTP_500_INTERNAL_ERROR);
|
||||
result.header(Constants.HEADER_CONTENT_TYPE, Constants.CT_TEXT_WITH_UTF8);
|
||||
result.header(Constants.HEADER_CONTENT_ENCODING, Constants.CHARSET_NAME_UTF8);
|
||||
result.entity(theException.getMessage());
|
||||
return result.build();
|
||||
}
|
||||
} else {
|
||||
ourLog.error("Unknown error during processing", theException);
|
||||
}
|
||||
|
||||
// Add headers associated with the specific error code
|
||||
if (theException instanceof BaseServerResponseException) {
|
||||
final Map<String, String[]> additional = ((BaseServerResponseException) theException).getAssociatedHeaders();
|
||||
if (additional != null) {
|
||||
for (final Entry<String, String[]> next : additional.entrySet()) {
|
||||
if (isNotBlank(next.getKey()) && next.getValue() != null) {
|
||||
final String nextKey = next.getKey();
|
||||
for (final String nextValue : next.getValue()) {
|
||||
addHeader(nextKey, nextValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final boolean requestIsBrowser = false; // RestfulServer.requestIsBrowser(theRequest);
|
||||
final String fhirServerBase = ""; // theRequestDetails.getFhirServerBase();
|
||||
|
||||
// theResponse.setStatus(statusCode);
|
||||
// theRequestDetails.getServer().addHeadersToResponse(theResponse);
|
||||
// theResponse.setContentType("text/plain");
|
||||
// theResponse.setCharacterEncoding("UTF-8");
|
||||
// theResponse.getWriter().append(theException.getMessage());
|
||||
// theResponse.getWriter().close();
|
||||
|
||||
final ResponseBuilder result = Response.status(statusCode);
|
||||
//final String resName = ctx.getResourceDefinition(oo).getName();
|
||||
result.header(Constants.HEADER_CONTENT_TYPE, Constants.CT_TEXT_WITH_UTF8);
|
||||
result.entity(theException.getMessage());
|
||||
return result.build();
|
||||
}
|
||||
|
||||
private void addHeader(final String nextKey, final String nextValue) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private void populateDetails(final FhirContext theCtx, final Throwable theException, final IBaseOperationOutcome theOo) {
|
||||
if (myReturnStackTracesForExceptionTypes != null) {
|
||||
for (final Class<?> next : myReturnStackTracesForExceptionTypes) {
|
||||
if (next.isAssignableFrom(theException.getClass())) {
|
||||
final String detailsValue = theException.getMessage() + "\n\n" + ExceptionUtils.getStackTrace(theException);
|
||||
OperationOutcomeUtil.addIssue(theCtx, theOo, "error", detailsValue);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OperationOutcomeUtil.addIssue(theCtx, theOo, "error", theException.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* If any server methods throw an exception which extends any of the given exception types, the exception stack trace
|
||||
* will be returned to the user. This can be useful for helping to diagnose issues, but may not be desirable for
|
||||
* production situations.
|
||||
*
|
||||
* @param theExceptionTypes
|
||||
* The exception types for which to return the stack trace to the user.
|
||||
* @return Returns an instance of this interceptor, to allow for easy method chaining.
|
||||
*/
|
||||
public ExceptionInterceptor setReturnStackTracesForExceptionTypes(final Class<?>... theExceptionTypes) {
|
||||
myReturnStackTracesForExceptionTypes = theExceptionTypes;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package ca.uhn.fhir.jaxrs.server.util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
|
||||
public class GZipUtil {
|
||||
|
||||
public static String decompress(byte[] theResource) {
|
||||
GZIPInputStream is;
|
||||
try {
|
||||
is = new GZIPInputStream(new ByteArrayInputStream(theResource));
|
||||
return IOUtils.toString(is, "UTF-8");
|
||||
} catch (IOException e) {
|
||||
throw new DataFormatException("Failed to decompress contents", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] compress(String theEncoded) {
|
||||
try {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
GZIPOutputStream gos = new GZIPOutputStream(os);
|
||||
IOUtils.write(theEncoded, gos, "UTF-8");
|
||||
gos.close();
|
||||
os.close();
|
||||
byte[] retVal = os.toByteArray();
|
||||
return retVal;
|
||||
} catch (IOException e) {
|
||||
throw new DataFormatException("Compress contents", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package ca.uhn.fhir.jaxrs.server.util;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jaxrs.server.AbstractResourceRestServer;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.CreateMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.DeleteMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.IParameter;
|
||||
import ca.uhn.fhir.rest.method.OperationMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.UpdateMethodBinding;
|
||||
import ca.uhn.fhir.rest.param.ResourceParameter;
|
||||
import ca.uhn.fhir.util.ReflectionUtil;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class MethodBindings {
|
||||
|
||||
/** BaseOutcomeReturningMethodBinding */
|
||||
private ConcurrentHashMap<String, CreateMethodBinding> createMethods = new ConcurrentHashMap<String, CreateMethodBinding>();
|
||||
private ConcurrentHashMap<String, UpdateMethodBinding> updateMethods = new ConcurrentHashMap<String, UpdateMethodBinding>();
|
||||
private ConcurrentHashMap<String, DeleteMethodBinding> delete = new ConcurrentHashMap<String, DeleteMethodBinding>();
|
||||
|
||||
/** BaseResourceReturingMethodBinding */
|
||||
private ConcurrentHashMap<String, SearchMethodBinding> searchMethods = new ConcurrentHashMap<String, SearchMethodBinding>();
|
||||
private ConcurrentHashMap<String, OperationMethodBinding> operationMethods = new ConcurrentHashMap<String, OperationMethodBinding>();
|
||||
|
||||
public <T extends AbstractResourceRestServer<?>> void findMethods(T theProvider, Class<?> subclass, FhirContext fhirContext) {
|
||||
for (final Method m : ReflectionUtil.getDeclaredMethods(subclass)) {
|
||||
final BaseMethodBinding<?> foundMethodBinding = BaseMethodBinding.bindMethod(m, fhirContext, theProvider);
|
||||
if(foundMethodBinding == null) {
|
||||
continue;
|
||||
}
|
||||
ConcurrentHashMap map = getMap(foundMethodBinding.getClass());
|
||||
if (map.contains(theProvider.getResourceType().getName())) {
|
||||
throw new IllegalArgumentException("Multiple Search Method Bindings Found : " + foundMethodBinding.getMethod() + " -- "
|
||||
+ foundMethodBinding.getMethod());
|
||||
} else {
|
||||
map.put(theProvider.getResourceType().getName(), foundMethodBinding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private <T> ConcurrentHashMap<String, T> getMap(Class<T> class1) {
|
||||
if(class1.isAssignableFrom(CreateMethodBinding.class)) return (ConcurrentHashMap<String, T>) createMethods;
|
||||
if(class1.isAssignableFrom(UpdateMethodBinding.class)) return (ConcurrentHashMap<String, T>) updateMethods;
|
||||
if(class1.isAssignableFrom(DeleteMethodBinding.class)) return (ConcurrentHashMap<String, T>) delete;
|
||||
if(class1.isAssignableFrom(SearchMethodBinding.class)) return (ConcurrentHashMap<String, T>) searchMethods;
|
||||
if(class1.isAssignableFrom(OperationMethodBinding.class)) return (ConcurrentHashMap<String, T>) operationMethods;
|
||||
return new ConcurrentHashMap();
|
||||
}
|
||||
|
||||
public Object[] createParams(IBaseResource resource, final BaseMethodBinding<?> method, final RequestDetails theRequest) {
|
||||
final Object[] paramsServer = new Object[method.getParameters().size()];
|
||||
for (int i = 0; i < method.getParameters().size(); i++) {
|
||||
final IParameter param = method.getParameters().get(i);
|
||||
if(param instanceof ResourceParameter) {
|
||||
paramsServer[i] = resource;
|
||||
} else {
|
||||
paramsServer[i] = param.translateQueryParametersIntoServerArgument(theRequest, null, method);
|
||||
}
|
||||
}
|
||||
return paramsServer;
|
||||
}
|
||||
|
||||
public <T> T getBinding(Class<T> clazz) {
|
||||
ConcurrentHashMap map = getMap((Class<? extends BaseMethodBinding>) clazz);
|
||||
if(map.values().size() == 0) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
return (T) map.values().iterator().next();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package ca.uhn.fhir.jaxrs.server.util;
|
||||
|
||||
import ca.uhn.fhir.rest.server.AddProfileTagEnum;
|
||||
import ca.uhn.fhir.rest.server.BundleInclusionRule;
|
||||
import ca.uhn.fhir.rest.server.ETagSupportEnum;
|
||||
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||
import ca.uhn.fhir.rest.server.IPagingProvider;
|
||||
import ca.uhn.fhir.rest.server.IRestfulServerDefaults;
|
||||
|
||||
public class RestfulServerDefaults implements IRestfulServerDefaults {
|
||||
|
||||
public boolean isUseBrowserFriendlyContentTypes() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public ETagSupportEnum getETagSupport() {
|
||||
return ETagSupportEnum.DISABLED;
|
||||
}
|
||||
|
||||
public AddProfileTagEnum getAddProfileTag() {
|
||||
return AddProfileTagEnum.NEVER;
|
||||
}
|
||||
|
||||
public boolean isDefaultPrettyPrint() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public IPagingProvider getPagingProvider() {
|
||||
//Integer count = getIntParam("_count");
|
||||
Integer count = 0;
|
||||
return count == 0 ? null : new FifoMemoryPagingProvider(count);
|
||||
}
|
||||
|
||||
public BundleInclusionRule getBundleInclusionRule() {
|
||||
return BundleInclusionRule.BASED_ON_INCLUDES;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,287 @@
|
|||
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.BoundCodeDt;
|
||||
import ca.uhn.fhir.model.primitive.DateDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryTransactionMethodEnum;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||
import ca.uhn.fhir.rest.method.SearchStyleEnum;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
|
||||
@Ignore
|
||||
public class DemoTest {
|
||||
|
||||
private static final String serverBase = "http://localhost:8580/hapi-fhir-jaxrsserver-example/jaxrs-demo/";
|
||||
private static IGenericClient client;
|
||||
|
||||
//START SNIPPET: client
|
||||
@BeforeClass
|
||||
public static void setUpOnce() {
|
||||
final FhirContext ctx = FhirContext.forDstu2();
|
||||
client = ctx.newRestfulGenericClient(serverBase);
|
||||
client.setEncoding(EncodingEnum.JSON);
|
||||
}
|
||||
|
||||
//END SNIPPET: client
|
||||
|
||||
/** Search/Query - Type */
|
||||
@Test
|
||||
public void findUsingGenericClientBySearch() {
|
||||
// Perform a search
|
||||
final ca.uhn.fhir.model.api.Bundle results = client.search().forResource(Patient.class)
|
||||
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("SHORTNAME", "TOYS")).execute();
|
||||
System.out.println(results.getEntries().get(0));
|
||||
assertEquals(results.getEntries().size(), 1);
|
||||
}
|
||||
|
||||
/** Search - Multi-valued Parameters (ANY/OR) */
|
||||
@Test
|
||||
public void findUsingGenericClientBySearchWithMultiValues() {
|
||||
final ca.uhn.fhir.model.api.Bundle response = client.search().forResource(Patient.class)
|
||||
.where(Patient.ADDRESS.matches().values("Toronto")).and(Patient.ADDRESS.matches().values("Ontario"))
|
||||
.and(Patient.ADDRESS.matches().values("Canada"))
|
||||
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("SHORTNAME", "TOYS")).execute();
|
||||
System.out.println(response.getEntries().get(0));
|
||||
}
|
||||
|
||||
/** Search - Paging */
|
||||
@Test
|
||||
public void findWithPaging() {
|
||||
// Perform a search
|
||||
for(int i = 0 ; i < 10 ; i++) {
|
||||
testCreatePatient();
|
||||
}
|
||||
final Bundle results = client.search().forResource(Patient.class).limitTo(8).returnBundle(Bundle.class).execute();
|
||||
System.out.println(results.getEntry().size());
|
||||
|
||||
if (results.getLink(Bundle.LINK_NEXT) != null) {
|
||||
|
||||
// load next page
|
||||
final Bundle nextPage = client.loadPage().next(results).execute();
|
||||
System.out.println(nextPage.getEntry().size());
|
||||
}
|
||||
}
|
||||
|
||||
/** Search using other query options */
|
||||
public void testOther() {
|
||||
//missing
|
||||
}
|
||||
|
||||
/** */
|
||||
@Test
|
||||
public void testSearchPost() {
|
||||
Bundle response = client.search()
|
||||
.forResource("Patient")
|
||||
.usingStyle(SearchStyleEnum.POST)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
assertTrue(response.getEntry().size() > 0);
|
||||
}
|
||||
|
||||
/** Search - Compartments */
|
||||
@Test
|
||||
public void testSearchCompartements() {
|
||||
Bundle response = client.search()
|
||||
.forResource(Patient.class)
|
||||
.withIdAndCompartment("1", "condition")
|
||||
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
|
||||
.execute();
|
||||
assertTrue(response.getEntry().size() > 0);
|
||||
}
|
||||
|
||||
/** Search - Subsetting (_summary and _elements) */
|
||||
@Test
|
||||
@Ignore
|
||||
public void testSummary() {
|
||||
Object response = client.search()
|
||||
.forResource(Patient.class)
|
||||
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
|
||||
.execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatePatient() {
|
||||
final Patient existing = new Patient();
|
||||
existing.setId((IdDt) null);
|
||||
existing.getNameFirstRep().addFamily("Created Patient 54");
|
||||
client.setEncoding(EncodingEnum.XML);
|
||||
final MethodOutcome results = client.create().resource(existing).execute();
|
||||
System.out.println(results.getId());
|
||||
final Bundle bundle = (Bundle) results.getResource();
|
||||
final Patient patient = (Patient) bundle.getEntryFirstRep().getResource();
|
||||
System.out.println(patient);
|
||||
assertNotNull(client.read(patient.getId()));
|
||||
client.setEncoding(EncodingEnum.JSON);
|
||||
}
|
||||
|
||||
|
||||
/** Conditional Creates */
|
||||
@Test
|
||||
public void testConditionalCreate() {
|
||||
final Patient existing = new Patient();
|
||||
existing.setId((IdDt) null);
|
||||
existing.getNameFirstRep().addFamily("Created Patient 54");
|
||||
client.setEncoding(EncodingEnum.XML);
|
||||
final MethodOutcome results = client.create().resource(existing).execute();
|
||||
System.out.println(results.getId());
|
||||
final Bundle bundle = (Bundle) results.getResource();
|
||||
final Patient patient = (Patient) bundle.getEntryFirstRep().getResource();
|
||||
|
||||
client.create()
|
||||
.resource(patient)
|
||||
.conditional()
|
||||
.where(Patient.IDENTIFIER.exactly().identifier(patient.getIdentifierFirstRep()))
|
||||
.execute();
|
||||
}
|
||||
|
||||
|
||||
/** Find By Id */
|
||||
@Test
|
||||
public void findUsingGenericClientById() {
|
||||
final Patient results = client.read(Patient.class, "1");
|
||||
assertTrue(results.getIdentifier().toString().contains("THOR"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateById() {
|
||||
final Patient existing = client.read(Patient.class, "1");
|
||||
final List<HumanNameDt> name = existing.getName();
|
||||
name.get(0).addSuffix("The Second");
|
||||
existing.setName(name);
|
||||
client.setEncoding(EncodingEnum.XML);
|
||||
final MethodOutcome results = client.update("1", existing);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeletePatient() {
|
||||
final Patient existing = new Patient();
|
||||
existing.getNameFirstRep().addFamily("Created Patient XYZ");
|
||||
final MethodOutcome results = client.create().resource(existing).execute();
|
||||
System.out.println(results.getId());
|
||||
final Bundle bundle = (Bundle) results.getResource();
|
||||
final Patient patient = (Patient) bundle.getEntryFirstRep().getResource();
|
||||
client.delete(Patient.class, patient.getId());
|
||||
try {
|
||||
assertNotNull(client.read(patient.getId()));
|
||||
}
|
||||
catch (final ResourceNotFoundException e) {
|
||||
assertEquals(e.getStatusCode(), Constants.STATUS_HTTP_404_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/** Transaction - Server */
|
||||
@Test
|
||||
public void testTransaction() {
|
||||
ca.uhn.fhir.model.api.Bundle bundle = new ca.uhn.fhir.model.api.Bundle();
|
||||
BundleEntry entry = bundle.addEntry();
|
||||
final Patient existing = new Patient();
|
||||
existing.getNameFirstRep().addFamily("Created with bundle");
|
||||
entry.setResource(existing);
|
||||
|
||||
BoundCodeDt<BundleEntryTransactionMethodEnum> theTransactionOperation =
|
||||
new BoundCodeDt(
|
||||
BundleEntryTransactionMethodEnum.VALUESET_BINDER,
|
||||
BundleEntryTransactionMethodEnum.POST);
|
||||
entry.setTransactionMethod(theTransactionOperation);
|
||||
ca.uhn.fhir.model.api.Bundle response = client.transaction().withBundle(bundle).execute();
|
||||
}
|
||||
|
||||
/** Conformance - Server */
|
||||
@Test
|
||||
public void testConformance() {
|
||||
final Conformance conf = client.fetchConformance().ofType(Conformance.class).execute();
|
||||
System.out.println(conf.getRest().get(0).getResource().get(0).getType());
|
||||
System.out.println(conf.getRest().get(0).getResource().get(1).getType());
|
||||
}
|
||||
|
||||
/** Extended Operations */
|
||||
// Create a client to talk to the HeathIntersections server
|
||||
@Test
|
||||
public void testExtendedOperations() {
|
||||
client.registerInterceptor(new LoggingInterceptor(true));
|
||||
|
||||
// Create the input parameters to pass to the server
|
||||
Parameters inParams = new Parameters();
|
||||
inParams.addParameter().setName("start").setValue(new DateDt("2001-01-01"));
|
||||
inParams.addParameter().setName("end").setValue(new DateDt("2015-03-01"));
|
||||
inParams.addParameter().setName("dummy").setValue(new StringDt("myAwesomeDummyValue"));
|
||||
|
||||
// Invoke $everything on "Patient/1"
|
||||
Parameters outParams = client
|
||||
.operation()
|
||||
.onInstance(new IdDt("Patient", "1"))
|
||||
.named("$last")
|
||||
.withParameters(inParams)
|
||||
//.useHttpGet() // Use HTTP GET instead of POST
|
||||
.execute();
|
||||
String resultValue = outParams.getParameter().get(0).getValue().toString();
|
||||
System.out.println(resultValue);
|
||||
assertEquals("expected but found : "+ resultValue, resultValue.contains("myAwesomeDummyValue"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtendedOperationsUsingGet() {
|
||||
client.registerInterceptor(new LoggingInterceptor(true));
|
||||
|
||||
// Create the input parameters to pass to the server
|
||||
Parameters inParams = new Parameters();
|
||||
inParams.addParameter().setName("start").setValue(new DateDt("2001-01-01"));
|
||||
inParams.addParameter().setName("end").setValue(new DateDt("2015-03-01"));
|
||||
inParams.addParameter().setName("dummy").setValue(new StringDt("myAwesomeDummyValue"));
|
||||
|
||||
// Invoke $everything on "Patient/1"
|
||||
Parameters outParams = client
|
||||
.operation()
|
||||
.onInstance(new IdDt("Patient", "1"))
|
||||
.named("$last")
|
||||
.withParameters(inParams)
|
||||
.useHttpGet() // Use HTTP GET instead of POST
|
||||
.execute();
|
||||
String resultValue = outParams.getParameter().get(0).getValue().toString();
|
||||
System.out.println(resultValue);
|
||||
assertEquals("expected but found : "+ resultValue, resultValue.contains("myAwesomeDummyValue"), true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testFindUnknownPatient() {
|
||||
try {
|
||||
final Patient existing = client.read(Patient.class, "999955541264");
|
||||
}
|
||||
catch (final ResourceNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
assertEquals(e.getStatusCode(), 404);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVRead() {
|
||||
final Patient patient = client.vread(Patient.class, "1", "1");
|
||||
System.out.println(patient);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<!-- Note: HAPI projects use the "hapi-fhir" POM as their base to provide easy management. You do not need to use this in your own projects, so the "parent" tag and it's contents below may be removed
|
||||
if you are using this file as a basis for your own project. -->
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-jaxrsserver-example</artifactId>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<name>HAPI FHIR JPA Server - Example</name>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>oss-snapshots</id>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- This dependency includes the core HAPI-FHIR classes -->
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jaxrsserver-base</artifactId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
<build>
|
||||
|
||||
<!-- Tells Maven to name the generated WAR file as hapi-fhir-jpaserver-example.war -->
|
||||
<finalName>hapi-fhir-jaxrsserver-example</finalName>
|
||||
<!-- This is to run the integration tests -->
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<configuration>
|
||||
<redirectTestOutputToFile>true</redirectTestOutputToFile>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>unpack</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>${project.artifactId}</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>war</type>
|
||||
<includes>*.war</includes>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
<outputDirectory>C:\Agfa\ORBIS-AS\server\orbis-as-08.05.07.00.0009200-UK\standalone\deployments</outputDirectory>
|
||||
<stripVersion>true</stripVersion>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
|
||||
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,41 @@
|
|||
package ca.uhn.fhir.jaxrs.server.example;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.ejb.EJB;
|
||||
import javax.ejb.Local;
|
||||
import javax.ejb.Stateless;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
/**
|
||||
* Conformance Rest Service
|
||||
* @author Peter Van Houte
|
||||
*/
|
||||
@Local
|
||||
@Path(ConformanceRestServer.PATH)
|
||||
@Stateless
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class ConformanceRestServer extends ca.uhn.fhir.jaxrs.server.AbstractConformanceRestServer {
|
||||
|
||||
private static final String SERVER_VERSION = "1.0.0";
|
||||
private static final String SERVER_DESCRIPTION = "Jax-Rs Test Example Description";
|
||||
private static final String SERVER_NAME = "Jax-Rs Test Example";
|
||||
|
||||
@EJB
|
||||
private ConformanceRestServer conformanceRestServer;
|
||||
@EJB
|
||||
private IFhirPatientRestServer patientRestServer;
|
||||
|
||||
public ConformanceRestServer() {
|
||||
super(SERVER_DESCRIPTION, SERVER_NAME, SERVER_VERSION);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void createMethod()
|
||||
throws Exception {
|
||||
findResourceMethods(conformanceRestServer, ConformanceRestServer.class);
|
||||
findResourceMethods(patientRestServer, FhirPatientRestServer.class);
|
||||
super.setUpPostConstruct();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ca.uhn.fhir.jaxrs.server.example;
|
||||
|
||||
import javax.ws.rs.ApplicationPath;
|
||||
import javax.ws.rs.core.Application;
|
||||
|
||||
/**
|
||||
* Fhir Patient Demo Application
|
||||
* @author Peter Van Houte
|
||||
*/
|
||||
@ApplicationPath(value=FhirPatientDemoApplication.PATH)
|
||||
public class FhirPatientDemoApplication extends Application {
|
||||
public final static String PATH = "/jaxrs-demo";
|
||||
}
|
|
@ -0,0 +1,222 @@
|
|||
package ca.uhn.fhir.jaxrs.server.example;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.ejb.Stateless;
|
||||
import javax.interceptor.Interceptors;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import ca.uhn.fhir.jaxrs.server.AbstractResourceRestServer;
|
||||
import ca.uhn.fhir.jaxrs.server.interceptor.ExceptionInterceptor;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.Delete;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.annotation.Read;
|
||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.annotation.Update;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
|
||||
/**
|
||||
* Fhir Physician Rest Service
|
||||
* @author axmpm
|
||||
*
|
||||
*/
|
||||
@Local(IFhirPatientRestServer.class)
|
||||
@Path(FhirPatientRestServer.PATH)
|
||||
@Stateless
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class FhirPatientRestServer extends AbstractResourceRestServer<Patient> implements IFhirPatientRestServer {
|
||||
|
||||
static final String PATH = "/Patient";
|
||||
|
||||
private static Long counter = 1L;
|
||||
private static final ConcurrentHashMap<String, List<Patient>> patients = new ConcurrentHashMap<String, List<Patient>>();
|
||||
|
||||
protected FhirPatientRestServer() throws Exception {
|
||||
super(FhirPatientRestServer.class);
|
||||
}
|
||||
|
||||
static {
|
||||
patients.put(""+counter, createPatient("Agfa"));
|
||||
patients.put(""+(counter), createPatient("Healthcare"));
|
||||
for(int i = 0 ; i<20 ; i++) {
|
||||
patients.put(""+(counter), createPatient("Random Patient " + counter));
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Patient> createPatient(final String name) {
|
||||
final Patient patient = new Patient();
|
||||
patient.getNameFirstRep().addFamily(name);
|
||||
return createPatient(patient);
|
||||
}
|
||||
|
||||
private static List<Patient> createPatient(final Patient patient) {
|
||||
patient.setId(createId(counter, 1L));
|
||||
final LinkedList<Patient> list = new LinkedList<Patient>();
|
||||
list.add(patient);
|
||||
counter++;
|
||||
return list ;
|
||||
}
|
||||
|
||||
private static IdDt createId(final Long id, final Long theVersionId) {
|
||||
return new IdDt("Patient", "" + id, "" + theVersionId);
|
||||
}
|
||||
|
||||
@Search
|
||||
@Override
|
||||
public List<Patient> search(@RequiredParam(name = Patient.SP_NAME) final StringParam name) {
|
||||
final List<Patient> result = new LinkedList<Patient>();
|
||||
for (final List<Patient> patientIterator : patients.values()) {
|
||||
Patient single = null;
|
||||
for (Patient patient : patientIterator) {
|
||||
if (name == null || patient.getNameFirstRep().getFamilyFirstRep().getValueNotNull().equals(name.getValueNotNull())) {
|
||||
single = patient;
|
||||
}
|
||||
}
|
||||
if (single != null) {
|
||||
result.add(single);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Update
|
||||
@Override
|
||||
public MethodOutcome update(@IdParam final IdDt theId, @ResourceParam final Patient patient)
|
||||
throws Exception {
|
||||
final String idPart = theId.getIdPart();
|
||||
if(patients.containsKey(idPart)) {
|
||||
final List<Patient> patientList = patients.get(idPart);
|
||||
final Patient lastPatient = getLast(patientList);
|
||||
patient.setId(createId(theId.getIdPartAsLong(), lastPatient.getId().getVersionIdPartAsLong()+1));
|
||||
patientList.add(patient);
|
||||
final MethodOutcome result = new MethodOutcome().setCreated(false);
|
||||
result.setResource(patient);
|
||||
result.setId(patient.getId());
|
||||
return result;
|
||||
} else {
|
||||
throw new ResourceNotFoundException(theId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Read
|
||||
public Patient find(@IdParam final IdDt theId) {
|
||||
if(patients.containsKey(theId.getIdPart())) {
|
||||
return getLast(patients.get(theId.getIdPart()));
|
||||
} else {
|
||||
throw new ResourceNotFoundException(theId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Patient getLast(final List<Patient> list) {
|
||||
return list.get(list.size()-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Read(version = false)
|
||||
public Patient findHistory(@IdParam final IdDt theId) {
|
||||
if (patients.containsKey(theId.getIdPart())) {
|
||||
final List<Patient> list = patients.get(theId.getIdPart());
|
||||
for (final Patient patient : list) {
|
||||
if (patient.getId().getVersionIdPartAsLong().equals(theId.getVersionIdPartAsLong())) {
|
||||
return patient;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new ResourceNotFoundException(theId);
|
||||
}
|
||||
|
||||
@Create
|
||||
@Override
|
||||
public MethodOutcome create(@ResourceParam final Patient patient, @ConditionalUrlParam String theConditional)
|
||||
throws Exception {
|
||||
patients.put(""+counter, createPatient(patient));
|
||||
final MethodOutcome result = new MethodOutcome().setCreated(true);
|
||||
result.setResource(patient);
|
||||
result.setId(patient.getId());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Delete
|
||||
@Override
|
||||
public MethodOutcome delete(@IdParam final IdDt theId) {
|
||||
final Patient deletedPatient = find(theId);
|
||||
patients.remove(deletedPatient.getId().getIdPart());
|
||||
final MethodOutcome result = new MethodOutcome().setCreated(true);
|
||||
result.setResource(deletedPatient);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@GET
|
||||
@Path("/{id}/$last")
|
||||
@Interceptors(ExceptionInterceptor.class)
|
||||
@Override
|
||||
public Response operationLastGet(final String resource)
|
||||
throws Exception {
|
||||
return customOperation(null, RequestTypeEnum.GET);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/{id}/$last")
|
||||
@Interceptors(ExceptionInterceptor.class)
|
||||
@Override
|
||||
public Response operationLast(final String resource)
|
||||
throws Exception {
|
||||
return customOperation(getParser().parseResource(resource), RequestTypeEnum.POST);
|
||||
}
|
||||
|
||||
// @ca.uhn.fhir.rest.annotation.Validate
|
||||
// public MethodOutcome validate(
|
||||
// @ResourceParam T theResource,
|
||||
// @ResourceParam String theRawResource,
|
||||
// @ResourceParam EncodingEnum theEncoding,
|
||||
// @ca.uhn.fhir.rest.annotation.Validate.Mode ValidationModeEnum theMode,
|
||||
// @ca.uhn.fhir.rest.annotation.Validate.Profile String theProfile) {
|
||||
// return validate(theResource, null, theRawResource, theEncoding, theMode, theProfile);
|
||||
// }
|
||||
|
||||
@Operation(name="last", idempotent=true, returnParameters= {
|
||||
@OperationParam(name="return", type=StringDt.class)
|
||||
})
|
||||
@Override
|
||||
public Parameters last(@OperationParam(name = "dummy") StringDt dummyInput) {
|
||||
System.out.println("inputparameter");
|
||||
Parameters parameters = new Parameters();
|
||||
Patient patient = find(new IdDt(counter.intValue()-1));
|
||||
parameters
|
||||
.addParameter()
|
||||
.setName("return")
|
||||
.setResource(patient)
|
||||
.setValue(new StringDt((counter-1)+"" + "inputVariable [ " + dummyInput.getValue()+ "]"));
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Patient> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package ca.uhn.fhir.jaxrs.server.example;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
|
||||
public interface IFhirPatientRestServer extends IResourceProvider {
|
||||
|
||||
List<Patient> search(StringParam name);
|
||||
|
||||
MethodOutcome update(IdDt theId, Patient patient)
|
||||
throws Exception;
|
||||
|
||||
Patient find(IdDt theId);
|
||||
|
||||
Patient findHistory(IdDt theId);
|
||||
|
||||
MethodOutcome create(Patient patient, String theConditional)
|
||||
throws Exception;
|
||||
|
||||
MethodOutcome delete(IdDt theId);
|
||||
|
||||
Response operationLastGet(String resource)
|
||||
throws Exception;
|
||||
|
||||
Response operationLast(String resource)
|
||||
throws Exception;
|
||||
|
||||
Parameters last(StringDt dummyInput);
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
version="3.0" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee ./xsd/web-app_3_0.xsd">
|
||||
|
||||
<!-- This filters provide support for Cross Origin Resource Sharing (CORS) -->
|
||||
<!--
|
||||
<filter>
|
||||
<filter-name>CORS Filter</filter-name>
|
||||
<filter-class>org.ebaysf.web.cors.CORSFilter</filter-class>
|
||||
<init-param>
|
||||
<description>A comma separated list of allowed origins. Note: An '*' cannot be used for an allowed origin when using credentials.</description>
|
||||
<param-name>cors.allowed.origins</param-name>
|
||||
<param-value>*</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<description>A comma separated list of HTTP verbs, using which a CORS request can be made.</description>
|
||||
<param-name>cors.allowed.methods</param-name>
|
||||
<param-value>GET,POST,PUT,DELETE,OPTIONS</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<description>A comma separated list of allowed headers when making a non simple CORS request.</description>
|
||||
<param-name>cors.allowed.headers</param-name>
|
||||
<param-value>X-FHIR-Starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<description>A comma separated list non-standard response headers that will be exposed to XHR2 object.</description>
|
||||
<param-name>cors.exposed.headers</param-name>
|
||||
<param-value>Location,Content-Location</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<description>A flag that suggests if CORS is supported with cookies</description>
|
||||
<param-name>cors.support.credentials</param-name>
|
||||
<param-value>true</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<description>A flag to control logging</description>
|
||||
<param-name>cors.logging.enabled</param-name>
|
||||
<param-value>true</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<description>Indicates how long (in seconds) the results of a preflight request can be cached in a preflight result cache.</description>
|
||||
<param-name>cors.preflight.maxage</param-name>
|
||||
<param-value>300</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>CORS Filter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
-->
|
||||
|
||||
</web-app>
|
|
@ -22,13 +22,17 @@ package ca.uhn.fhir.rest.server.provider;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
|
@ -49,6 +53,7 @@ import ca.uhn.fhir.model.primitive.CodeDt;
|
|||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.annotation.Metadata;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.DynamicSearchMethodBinding;
|
||||
|
@ -59,10 +64,9 @@ import ca.uhn.fhir.rest.server.Constants;
|
|||
import ca.uhn.fhir.rest.server.IServerConformanceProvider;
|
||||
import ca.uhn.fhir.rest.server.ResourceBinding;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.RestulfulServerConfiguration;
|
||||
import ca.uhn.fhir.util.ExtensionConstants;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Server FHIR Provider which serves the conformance statement for a RESTful server implementation
|
||||
*
|
||||
|
@ -78,10 +82,10 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
private boolean myCache = true;
|
||||
private volatile Conformance myConformance;
|
||||
private String myPublisher = "Not provided";
|
||||
private RestfulServer myRestfulServer;
|
||||
private RestulfulServerConfiguration myRestfulServer;
|
||||
|
||||
public ServerConformanceProvider(RestfulServer theRestfulServer) {
|
||||
myRestfulServer = theRestfulServer;
|
||||
myRestfulServer = new RestulfulServerConfiguration(theRestfulServer);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -95,7 +99,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
}
|
||||
|
||||
public void setRestfulServer (RestfulServer theRestfulServer) {
|
||||
myRestfulServer = theRestfulServer;
|
||||
myRestfulServer = new RestulfulServerConfiguration(theRestfulServer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,15 +21,21 @@ package ca.uhn.fhir.rest.server.provider.dstu2;
|
|||
*/
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
|
@ -53,6 +59,7 @@ import ca.uhn.fhir.model.dstu2.valueset.TypeRestfulInteractionEnum;
|
|||
import ca.uhn.fhir.model.dstu2.valueset.UnknownContentCodeEnum;
|
||||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Initialize;
|
||||
import ca.uhn.fhir.rest.annotation.Metadata;
|
||||
|
@ -69,6 +76,7 @@ import ca.uhn.fhir.rest.server.Constants;
|
|||
import ca.uhn.fhir.rest.server.IServerConformanceProvider;
|
||||
import ca.uhn.fhir.rest.server.ResourceBinding;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.RestulfulServerConfiguration;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
|
||||
/**
|
||||
|
@ -86,10 +94,14 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
private IdentityHashMap<OperationMethodBinding, String> myOperationBindingToName;
|
||||
private HashMap<String, List<OperationMethodBinding>> myOperationNameToBindings;
|
||||
private String myPublisher = "Not provided";
|
||||
private RestfulServer myRestfulServer;
|
||||
private RestulfulServerConfiguration myServerConfiguration;
|
||||
|
||||
public ServerConformanceProvider(RestfulServer theRestfulServer) {
|
||||
myRestfulServer = theRestfulServer;
|
||||
this.myServerConfiguration = new RestulfulServerConfiguration(theRestfulServer);
|
||||
}
|
||||
|
||||
public ServerConformanceProvider(RestulfulServerConfiguration theServerConfiguration) {
|
||||
this.myServerConfiguration = theServerConfiguration;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -103,7 +115,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
}
|
||||
|
||||
public void setRestfulServer (RestfulServer theRestfulServer) {
|
||||
myRestfulServer = theRestfulServer;
|
||||
myServerConfiguration = new RestulfulServerConfiguration(theRestfulServer);
|
||||
}
|
||||
|
||||
private void checkBindingForSystemOps(Rest rest, Set<SystemRestfulInteractionEnum> systemOps, BaseMethodBinding<?> nextMethodBinding) {
|
||||
|
@ -124,7 +136,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
|
||||
private Map<String, List<BaseMethodBinding<?>>> collectMethodBindings() {
|
||||
Map<String, List<BaseMethodBinding<?>>> resourceToMethods = new TreeMap<String, List<BaseMethodBinding<?>>>();
|
||||
for (ResourceBinding next : myRestfulServer.getResourceBindings()) {
|
||||
for (ResourceBinding next : myServerConfiguration.getResourceBindings()) {
|
||||
String resourceName = next.getResourceName();
|
||||
for (BaseMethodBinding<?> nextMethodBinding : next.getMethodBindings()) {
|
||||
if (resourceToMethods.containsKey(resourceName) == false) {
|
||||
|
@ -133,7 +145,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
resourceToMethods.get(resourceName).add(nextMethodBinding);
|
||||
}
|
||||
}
|
||||
for (BaseMethodBinding<?> nextMethodBinding : myRestfulServer.getServerBindings()) {
|
||||
for (BaseMethodBinding<?> nextMethodBinding : myServerConfiguration.getServerBindings()) {
|
||||
String resourceName = "";
|
||||
if (resourceToMethods.containsKey(resourceName) == false) {
|
||||
resourceToMethods.put(resourceName, new ArrayList<BaseMethodBinding<?>>());
|
||||
|
@ -170,10 +182,10 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
retVal.setAcceptUnknown(UnknownContentCodeEnum.UNKNOWN_EXTENSIONS); // TODO: make this configurable - this is a fairly big effort since the parser
|
||||
// needs to be modified to actually allow it
|
||||
|
||||
retVal.getImplementation().setDescription(myRestfulServer.getImplementationDescription());
|
||||
retVal.getImplementation().setDescription(myServerConfiguration.getImplementationDescription());
|
||||
retVal.setKind(ConformanceStatementKindEnum.INSTANCE);
|
||||
retVal.getSoftware().setName(myRestfulServer.getServerName());
|
||||
retVal.getSoftware().setVersion(myRestfulServer.getServerVersion());
|
||||
retVal.getSoftware().setName(myServerConfiguration.getServerName());
|
||||
retVal.getSoftware().setVersion(myServerConfiguration.getServerVersion());
|
||||
retVal.addFormat(Constants.CT_FHIR_XML);
|
||||
retVal.addFormat(Constants.CT_FHIR_JSON);
|
||||
|
||||
|
@ -190,9 +202,9 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
Set<TypeRestfulInteractionEnum> resourceOps = new HashSet<TypeRestfulInteractionEnum>();
|
||||
RestResource resource = rest.addResource();
|
||||
String resourceName = nextEntry.getKey();
|
||||
RuntimeResourceDefinition def = myRestfulServer.getFhirContext().getResourceDefinition(resourceName);
|
||||
RuntimeResourceDefinition def = myServerConfiguration.getFhirContext().getResourceDefinition(resourceName);
|
||||
resource.getTypeElement().setValue(def.getName());
|
||||
resource.getProfile().setReference(new IdDt(def.getResourceProfile(myRestfulServer.getServerBaseForRequest(theRequest))));
|
||||
resource.getProfile().setReference(new IdDt(def.getResourceProfile(myServerConfiguration.getServerBaseForRequest(theRequest))));
|
||||
|
||||
TreeSet<String> includes = new TreeSet<String>();
|
||||
|
||||
|
@ -297,7 +309,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
}
|
||||
|
||||
private DateTimeDt conformanceDate() {
|
||||
String buildDate = getBuildDateFromManifest();
|
||||
String buildDate = myServerConfiguration.getConformanceDate();
|
||||
if (buildDate != null) {
|
||||
try {
|
||||
return new DateTimeDt(buildDate);
|
||||
|
@ -308,21 +320,6 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
return DateTimeDt.withCurrentTime();
|
||||
}
|
||||
|
||||
private String getBuildDateFromManifest() {
|
||||
if (myRestfulServer != null && myRestfulServer.getServletContext() != null) {
|
||||
InputStream inputStream = myRestfulServer.getServletContext().getResourceAsStream("/META-INF/MANIFEST.MF");
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
Manifest manifest = new Manifest(inputStream);
|
||||
return manifest.getMainAttributes().getValue("Build-Time");
|
||||
} catch (IOException e) {
|
||||
// fall through
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void handleDynamicSearchMethodBinding(RestResource resource, RuntimeResourceDefinition def, TreeSet<String> includes, DynamicSearchMethodBinding searchMethodBinding) {
|
||||
includes.addAll(searchMethodBinding.getIncludes());
|
||||
|
||||
|
@ -427,7 +424,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider<Con
|
|||
param.getTypeElement().setValueAsString(nextParameter.getParamType().getCode());
|
||||
}
|
||||
for (Class<? extends IResource> nextTarget : nextParameter.getDeclaredTypes()) {
|
||||
RuntimeResourceDefinition targetDef = myRestfulServer.getFhirContext().getResourceDefinition(nextTarget);
|
||||
RuntimeResourceDefinition targetDef = myServerConfiguration.getFhirContext().getResourceDefinition(nextTarget);
|
||||
if (targetDef != null) {
|
||||
ResourceTypeEnum code = ResourceTypeEnum.VALUESET_BINDER.fromCodeString(targetDef.getName());
|
||||
if (code != null) {
|
||||
|
|
Loading…
Reference in New Issue