Merge branch 'master' of github.com:jamesagnew/hapi-fhir
This commit is contained in:
commit
e9653cf6aa
|
@ -15,6 +15,11 @@
|
|||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.context;
|
||||
|
||||
/*
|
||||
* #%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%
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
|
|
@ -67,7 +67,7 @@ import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
|||
import ca.uhn.fhir.util.ReflectionUtil;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
|
||||
abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Object> {
|
||||
public abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Object> {
|
||||
protected static final Set<String> ALLOWED_PARAMS;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseResourceReturningMethodBinding.class);
|
||||
|
||||
|
@ -102,8 +102,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
Class<?> collectionType = ReflectionUtil.getGenericCollectionTypeOfMethodReturnType(theMethod);
|
||||
if (collectionType != null) {
|
||||
if (!Object.class.equals(collectionType) && !IBaseResource.class.isAssignableFrom(collectionType)) {
|
||||
throw new ConfigurationException("Method " + theMethod.getDeclaringClass().getSimpleName() + "#" + theMethod.getName() + " returns an invalid collection generic type: "
|
||||
+ collectionType);
|
||||
throw new ConfigurationException(
|
||||
"Method " + theMethod.getDeclaringClass().getSimpleName() + "#" + theMethod.getName() + " returns an invalid collection generic type: " + collectionType);
|
||||
}
|
||||
}
|
||||
myResourceListCollectionType = collectionType;
|
||||
|
@ -121,8 +121,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
} else if (MethodOutcome.class.isAssignableFrom(methodReturnType)) {
|
||||
myMethodReturnType = MethodReturnTypeEnum.METHOD_OUTCOME;
|
||||
} else {
|
||||
throw new ConfigurationException("Invalid return type '" + methodReturnType.getCanonicalName() + "' on method '" + theMethod.getName() + "' on type: "
|
||||
+ theMethod.getDeclaringClass().getCanonicalName());
|
||||
throw new ConfigurationException(
|
||||
"Invalid return type '" + methodReturnType.getCanonicalName() + "' on method '" + theMethod.getName() + "' on type: " + theMethod.getDeclaringClass().getCanonicalName());
|
||||
}
|
||||
|
||||
if (theReturnResourceType != null) {
|
||||
|
@ -233,29 +233,52 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
throw new IllegalStateException("Should not get here!");
|
||||
}
|
||||
|
||||
public abstract Object invokeServer(RestfulServer theServer, RequestDetails theRequest, Object[] theMethodParams) throws InvalidRequestException, InternalErrorException;
|
||||
|
||||
@Override
|
||||
public void invokeServer(RestfulServer theServer, RequestDetails theRequest) throws BaseServerResponseException, IOException {
|
||||
|
||||
// Pretty print
|
||||
boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theServer, theRequest);
|
||||
|
||||
// Narrative mode
|
||||
Set<SummaryEnum> summaryMode = RestfulServerUtils.determineSummaryMode(theRequest);
|
||||
|
||||
// Determine response encoding
|
||||
EncodingEnum responseEncoding = RestfulServerUtils.determineResponseEncodingNoDefault(theRequest.getServletRequest(), theServer.getDefaultResponseEncoding());
|
||||
|
||||
// Is this request coming from a browser
|
||||
String uaHeader = theRequest.getServletRequest().getHeader("user-agent");
|
||||
boolean requestIsBrowser = false;
|
||||
if (uaHeader != null && uaHeader.contains("Mozilla")) {
|
||||
requestIsBrowser = true;
|
||||
}
|
||||
|
||||
byte[] requestContents = loadRequestContents(theRequest);
|
||||
|
||||
final ResourceOrDstu1Bundle responseObject = invokeServer(theServer, theRequest, requestContents);
|
||||
|
||||
Set<SummaryEnum> summaryMode = RestfulServerUtils.determineSummaryMode(theRequest);
|
||||
if (responseObject.getResource() != null) {
|
||||
|
||||
for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
|
||||
IServerInterceptor next = theServer.getInterceptors().get(i);
|
||||
boolean continueProcessing = next.outgoingResponse(theRequest, responseObject.getResource(), theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||
if (!continueProcessing) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theServer, theRequest);
|
||||
HttpServletResponse response = theRequest.getServletResponse();
|
||||
RestfulServerUtils.streamResponseAsResource(theServer, response, responseObject.getResource(), prettyPrint, summaryMode, Constants.STATUS_HTTP_200_OK, theRequest.isRespondGzip(),
|
||||
isAddContentLocationHeader(), theRequest);
|
||||
} else {
|
||||
// Is this request coming from a browser
|
||||
String uaHeader = theRequest.getServletRequest().getHeader("user-agent");
|
||||
boolean requestIsBrowser = false;
|
||||
if (uaHeader != null && uaHeader.contains("Mozilla")) {
|
||||
requestIsBrowser = true;
|
||||
}
|
||||
|
||||
for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
|
||||
IServerInterceptor next = theServer.getInterceptors().get(i);
|
||||
boolean continueProcessing = next.outgoingResponse(theRequest, responseObject.getDstu1Bundle(), theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||
if (!continueProcessing) {
|
||||
ourLog.debug("Interceptor {} returned false, not continuing processing");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
HttpServletResponse response = theRequest.getServletResponse();
|
||||
RestfulServerUtils.streamResponseAsBundle(theServer, response, responseObject.getDstu1Bundle(), theRequest.getFhirServerBase(), summaryMode, theRequest.isRespondGzip(), requestIsBrowser,
|
||||
theRequest);
|
||||
}
|
||||
}
|
||||
|
||||
public ResourceOrDstu1Bundle invokeServer(RestfulServer theServer, RequestDetails theRequest, byte[] requestContents) {
|
||||
// Method params
|
||||
Object[] params = new Object[getParameters().size()];
|
||||
for (int i = 0; i < getParameters().size(); i++) {
|
||||
|
@ -267,9 +290,10 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
|
||||
Object resultObj = invokeServer(theServer, theRequest, params);
|
||||
|
||||
Integer count = RestfulServerUtils.extractCountParameter(theRequest.getServletRequest());
|
||||
boolean respondGzip = theRequest.isRespondGzip();
|
||||
HttpServletResponse response = theRequest.getServletResponse();
|
||||
Integer count = RestfulServerUtils.extractCountParameter(theRequest);
|
||||
|
||||
final ResourceOrDstu1Bundle responseObject;
|
||||
|
||||
switch (getReturnType()) {
|
||||
case BUNDLE: {
|
||||
|
||||
|
@ -323,17 +347,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
bundleFactory.initializeWithBundleResource(resource);
|
||||
bundleFactory.addRootPropertiesToBundle(null, theRequest.getFhirServerBase(), linkSelf, count, getResponseBundleType(), lastUpdated);
|
||||
|
||||
for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
|
||||
IServerInterceptor next = theServer.getInterceptors().get(i);
|
||||
boolean continueProcessing = next.outgoingResponse(theRequest, resource, theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||
if (!continueProcessing) {
|
||||
ourLog.debug("Interceptor {} returned false, not continuing processing");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
RestfulServerUtils.streamResponseAsResource(theServer, response, resource, prettyPrint, summaryMode, Constants.STATUS_HTTP_200_OK, respondGzip,
|
||||
isAddContentLocationHeader(), theRequest);
|
||||
responseObject = new ResourceOrDstu1Bundle(resource);
|
||||
break;
|
||||
} else {
|
||||
Set<Include> includes = getRequestIncludesFromParams(params);
|
||||
|
@ -344,32 +358,18 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
}
|
||||
|
||||
IVersionSpecificBundleFactory bundleFactory = theServer.getFhirContext().newBundleFactory();
|
||||
|
||||
EncodingEnum responseEncoding = RestfulServerUtils.determineResponseEncodingNoDefault(theRequest.getServletRequest(), theServer.getDefaultResponseEncoding());
|
||||
EncodingEnum linkEncoding = theRequest.getParameters().containsKey(Constants.PARAM_FORMAT) ? responseEncoding : null;
|
||||
bundleFactory.initializeBundleFromBundleProvider(theServer, result, linkEncoding, theRequest.getFhirServerBase(), linkSelf, prettyPrint, 0, count, null, getResponseBundleType(),
|
||||
includes);
|
||||
|
||||
boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theServer, theRequest);
|
||||
bundleFactory.initializeBundleFromBundleProvider(theServer, result, linkEncoding, theRequest.getFhirServerBase(), linkSelf, prettyPrint, 0, count, null, getResponseBundleType(), includes);
|
||||
Bundle bundle = bundleFactory.getDstu1Bundle();
|
||||
if (bundle != null) {
|
||||
for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
|
||||
IServerInterceptor next = theServer.getInterceptors().get(i);
|
||||
boolean continueProcessing = next.outgoingResponse(theRequest, bundle, theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||
if (!continueProcessing) {
|
||||
ourLog.debug("Interceptor {} returned false, not continuing processing");
|
||||
return;
|
||||
}
|
||||
}
|
||||
RestfulServerUtils.streamResponseAsBundle(theServer, response, bundle, theRequest.getFhirServerBase(), summaryMode, respondGzip, requestIsBrowser, theRequest);
|
||||
responseObject = new ResourceOrDstu1Bundle(bundle);
|
||||
} else {
|
||||
IBaseResource resBundle = bundleFactory.getResourceBundle();
|
||||
for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
|
||||
IServerInterceptor next = theServer.getInterceptors().get(i);
|
||||
boolean continueProcessing = next.outgoingResponse(theRequest, resBundle, theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||
if (!continueProcessing) {
|
||||
ourLog.debug("Interceptor {} returned false, not continuing processing");
|
||||
return;
|
||||
}
|
||||
}
|
||||
RestfulServerUtils.streamResponseAsResource(theServer, response, resBundle, prettyPrint, summaryMode,
|
||||
Constants.STATUS_HTTP_200_OK, theRequest.isRespondGzip(), isAddContentLocationHeader(), theRequest);
|
||||
responseObject = new ResourceOrDstu1Bundle(resBundle);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -384,22 +384,17 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
}
|
||||
|
||||
IBaseResource resource = result.getResources(0, 1).get(0);
|
||||
|
||||
for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
|
||||
IServerInterceptor next = theServer.getInterceptors().get(i);
|
||||
boolean continueProcessing = next.outgoingResponse(theRequest, resource, theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||
if (!continueProcessing) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
RestfulServerUtils.streamResponseAsResource(theServer, response, resource, prettyPrint, summaryMode, Constants.STATUS_HTTP_200_OK, respondGzip,
|
||||
isAddContentLocationHeader(), theRequest);
|
||||
responseObject = new ResourceOrDstu1Bundle(resource);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new IllegalStateException(); // should not happen
|
||||
}
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
public abstract Object invokeServer(RestfulServer theServer, RequestDetails theRequest, Object[] theMethodParams) throws InvalidRequestException, InternalErrorException;
|
||||
|
||||
/**
|
||||
* Should the response include a Content-Location header. Search method bunding (and any others?) may override this to disable the content-location, since it doesn't make sense
|
||||
*/
|
||||
|
@ -412,7 +407,32 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
}
|
||||
|
||||
public enum MethodReturnTypeEnum {
|
||||
BUNDLE, BUNDLE_PROVIDER, BUNDLE_RESOURCE, LIST_OF_RESOURCES, RESOURCE, METHOD_OUTCOME
|
||||
BUNDLE, BUNDLE_PROVIDER, BUNDLE_RESOURCE, LIST_OF_RESOURCES, METHOD_OUTCOME, RESOURCE
|
||||
}
|
||||
|
||||
public static class ResourceOrDstu1Bundle {
|
||||
|
||||
private final Bundle myDstu1Bundle;
|
||||
private final IBaseResource myResource;
|
||||
|
||||
public ResourceOrDstu1Bundle(Bundle theBundle) {
|
||||
myDstu1Bundle = theBundle;
|
||||
myResource = null;
|
||||
}
|
||||
|
||||
public ResourceOrDstu1Bundle(IBaseResource theResource) {
|
||||
myResource = theResource;
|
||||
myDstu1Bundle = null;
|
||||
}
|
||||
|
||||
public Bundle getDstu1Bundle() {
|
||||
return myDstu1Bundle;
|
||||
}
|
||||
|
||||
public IBaseResource getResource() {
|
||||
return myResource;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum ReturnTypeEnum {
|
||||
|
|
|
@ -388,6 +388,8 @@ public class MethodUtil {
|
|||
}
|
||||
if (parameterType.equals(HttpServletRequest.class) || parameterType.equals(ServletRequest.class)) {
|
||||
param = new ServletRequestParameter();
|
||||
} else if (parameterType.equals(RequestDetails.class)) {
|
||||
param = new RequestDetailsParameter();
|
||||
} else if (parameterType.equals(SummaryEnum.class)) {
|
||||
param = new SummaryEnumParameter();
|
||||
} else if (parameterType.equals(HttpServletResponse.class) || parameterType.equals(ServletResponse.class)) {
|
||||
|
|
|
@ -214,7 +214,7 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding implem
|
|||
IBundleProvider retVal = toResourceList(response);
|
||||
|
||||
if (theRequest.getServer().getETagSupport() == ETagSupportEnum.ENABLED) {
|
||||
String ifNoneMatch = theRequest.getServletRequest().getHeader(Constants.HEADER_IF_NONE_MATCH_LC);
|
||||
String ifNoneMatch = theRequest.getFirstHeader(Constants.HEADER_IF_NONE_MATCH_LC);
|
||||
if (retVal.size() == 1 && StringUtils.isNotBlank(ifNoneMatch)) {
|
||||
List<IBaseResource> responseResources = retVal.getResources(0, 1);
|
||||
IBaseResource responseResource = responseResources.get(0);
|
||||
|
|
|
@ -37,6 +37,7 @@ import ca.uhn.fhir.rest.server.RestfulServer;
|
|||
|
||||
public class RequestDetails {
|
||||
|
||||
private Map<String, ArrayList<String>> myHeaders = new HashMap<String, ArrayList<String>>();
|
||||
private String myCompartmentName;
|
||||
private String myCompleteUrl;
|
||||
private String myFhirServerBase;
|
||||
|
@ -230,4 +231,22 @@ public class RequestDetails {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
public void addHeader(String theName, String theValue) {
|
||||
String lowerCase = theName.toLowerCase();
|
||||
ArrayList<String> list = myHeaders.get(lowerCase);
|
||||
if (list == null) {
|
||||
list = new ArrayList<String>();
|
||||
myHeaders.put(lowerCase, list);
|
||||
}
|
||||
list.add(theValue);
|
||||
}
|
||||
|
||||
public String getFirstHeader(String theName) {
|
||||
ArrayList<String> list = myHeaders.get(theName.toLowerCase());
|
||||
if (list == null || list.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return list.get(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
/*
|
||||
* #%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%
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
class RequestDetailsParameter implements IParameter {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RequestDetailsParameter.class);
|
||||
|
||||
@Override
|
||||
public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map<String, List<String>> theTargetQueryArguments, IBaseResource theTargetResource) throws InternalErrorException {
|
||||
/*
|
||||
* Does nothing, since we just ignore HttpServletRequest arguments
|
||||
*/
|
||||
ourLog.trace("Ignoring RequestDetailsParameter argument: {}", theSourceClientArgument);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, byte[] theRequestContents, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||
return theRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
}
|
|
@ -52,9 +52,6 @@ import ca.uhn.fhir.rest.server.RestfulServer;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchMethodBinding.class);
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -477,14 +478,14 @@ public class RestfulServer extends HttpServlet {
|
|||
return;
|
||||
}
|
||||
|
||||
Integer count = RestfulServerUtils.extractCountParameter(theRequest.getServletRequest());
|
||||
Integer count = RestfulServerUtils.extractCountParameter(theRequest);
|
||||
if (count == null) {
|
||||
count = getPagingProvider().getDefaultPageSize();
|
||||
} else if (count > getPagingProvider().getMaximumPageSize()) {
|
||||
count = getPagingProvider().getMaximumPageSize();
|
||||
}
|
||||
|
||||
Integer offsetI = RestfulServerUtils.tryToExtractNamedParameter(theRequest.getServletRequest(), Constants.PARAM_PAGINGOFFSET);
|
||||
Integer offsetI = RestfulServerUtils.tryToExtractNamedParameter(theRequest, Constants.PARAM_PAGINGOFFSET);
|
||||
if (offsetI == null || offsetI < 0) {
|
||||
offsetI = 0;
|
||||
}
|
||||
|
@ -545,6 +546,12 @@ public class RestfulServer extends HttpServlet {
|
|||
requestDetails.setRequestType(theRequestType);
|
||||
requestDetails.setServletRequest(theRequest);
|
||||
requestDetails.setServletResponse(theResponse);
|
||||
for (Enumeration<String> iter = theRequest.getHeaderNames(); iter.hasMoreElements(); ) {
|
||||
String nextName = iter.nextElement();
|
||||
for (Enumeration<String> valueIter = theRequest.getHeaders(nextName); valueIter.hasMoreElements();) {
|
||||
requestDetails.addHeader(nextName, valueIter.nextElement());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
|
@ -556,7 +563,6 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
}
|
||||
|
||||
String resourceName = null;
|
||||
String requestFullPath = StringUtils.defaultString(theRequest.getRequestURI());
|
||||
String servletPath = StringUtils.defaultString(theRequest.getServletPath());
|
||||
StringBuffer requestUrl = theRequest.getRequestURL();
|
||||
|
@ -572,11 +578,9 @@ public class RestfulServer extends HttpServlet {
|
|||
ourLog.trace("Context Path: {}", servletContextPath);
|
||||
}
|
||||
|
||||
IdDt id = null;
|
||||
String operation = null;
|
||||
String compartment = null;
|
||||
|
||||
String requestPath = getRequestPath(requestFullPath, servletContextPath, servletPath);
|
||||
|
||||
if (requestPath.length() > 0 && requestPath.charAt(0) == '/') {
|
||||
requestPath = requestPath.substring(1);
|
||||
}
|
||||
|
@ -588,84 +592,16 @@ public class RestfulServer extends HttpServlet {
|
|||
Map<String, String[]> params = new HashMap<String, String[]>(theRequest.getParameterMap());
|
||||
requestDetails.setParameters(params);
|
||||
|
||||
StringTokenizer tok = new StringTokenizer(requestPath, "/");
|
||||
if (tok.hasMoreTokens()) {
|
||||
resourceName = tok.nextToken();
|
||||
if (partIsOperation(resourceName)) {
|
||||
operation = resourceName;
|
||||
resourceName = null;
|
||||
}
|
||||
}
|
||||
requestDetails.setResourceName(resourceName);
|
||||
|
||||
ResourceBinding resourceBinding = null;
|
||||
BaseMethodBinding<?> resourceMethod = null;
|
||||
if (Constants.URL_TOKEN_METADATA.equals(resourceName) || theRequestType == RequestTypeEnum.OPTIONS) {
|
||||
resourceMethod = myServerConformanceMethod;
|
||||
} else if (resourceName == null) {
|
||||
resourceBinding = myServerBinding;
|
||||
} else {
|
||||
resourceBinding = myResourceNameToBinding.get(resourceName);
|
||||
if (resourceBinding == null) {
|
||||
throw new InvalidRequestException("Unknown resource type '" + resourceName + "' - Server knows how to handle: " + myResourceNameToBinding.keySet());
|
||||
}
|
||||
}
|
||||
|
||||
if (tok.hasMoreTokens()) {
|
||||
String nextString = tok.nextToken();
|
||||
if (partIsOperation(nextString)) {
|
||||
operation = nextString;
|
||||
} else {
|
||||
id = new IdDt(resourceName, UrlUtil.unescape(nextString));
|
||||
}
|
||||
}
|
||||
|
||||
if (tok.hasMoreTokens()) {
|
||||
String nextString = tok.nextToken();
|
||||
if (nextString.equals(Constants.PARAM_HISTORY)) {
|
||||
if (tok.hasMoreTokens()) {
|
||||
String versionString = tok.nextToken();
|
||||
if (id == null) {
|
||||
throw new InvalidRequestException("Don't know how to handle request path: " + requestPath);
|
||||
}
|
||||
id = new IdDt(resourceName, id.getIdPart(), UrlUtil.unescape(versionString));
|
||||
} else {
|
||||
operation = Constants.PARAM_HISTORY;
|
||||
}
|
||||
} else if (partIsOperation(nextString)) {
|
||||
if (operation != null) {
|
||||
throw new InvalidRequestException("URL Path contains two operations: " + requestPath);
|
||||
}
|
||||
operation = nextString;
|
||||
} else {
|
||||
compartment = nextString;
|
||||
}
|
||||
}
|
||||
|
||||
// Secondary is for things like ..../_tags/_delete
|
||||
String secondaryOperation = null;
|
||||
|
||||
while (tok.hasMoreTokens()) {
|
||||
String nextString = tok.nextToken();
|
||||
if (operation == null) {
|
||||
operation = nextString;
|
||||
} else if (secondaryOperation == null) {
|
||||
secondaryOperation = nextString;
|
||||
} else {
|
||||
throw new InvalidRequestException("URL path has unexpected token '" + nextString + "' at the end: " + requestPath);
|
||||
}
|
||||
}
|
||||
IdDt id;
|
||||
populateRequestDetailsFromRequestPath(requestDetails, requestPath);
|
||||
|
||||
if (theRequestType == RequestTypeEnum.PUT) {
|
||||
String contentLocation = theRequest.getHeader(Constants.HEADER_CONTENT_LOCATION);
|
||||
if (contentLocation != null) {
|
||||
id = new IdDt(contentLocation);
|
||||
requestDetails.setId(id);
|
||||
}
|
||||
}
|
||||
requestDetails.setId(id);
|
||||
requestDetails.setOperation(operation);
|
||||
requestDetails.setSecondaryOperation(secondaryOperation);
|
||||
requestDetails.setCompartmentName(compartment);
|
||||
|
||||
String acceptEncoding = theRequest.getHeader(Constants.HEADER_ACCEPT_ENCODING);
|
||||
boolean respondGzip = false;
|
||||
|
@ -696,18 +632,7 @@ public class RestfulServer extends HttpServlet {
|
|||
return;
|
||||
}
|
||||
|
||||
if (resourceMethod == null) {
|
||||
if (resourceBinding != null) {
|
||||
resourceMethod = resourceBinding.getMethod(requestDetails);
|
||||
}
|
||||
}
|
||||
if (resourceMethod == null) {
|
||||
if (isBlank(requestPath)) {
|
||||
throw new InvalidRequestException(myFhirContext.getLocalizer().getMessage(RestfulServer.class, "rootRequest"));
|
||||
} else {
|
||||
throw new InvalidRequestException(myFhirContext.getLocalizer().getMessage(RestfulServer.class, "unknownMethod", theRequestType.name(), requestPath, params.keySet()));
|
||||
}
|
||||
}
|
||||
BaseMethodBinding<?> resourceMethod = determineResourceMethod(requestDetails, requestPath);
|
||||
|
||||
requestDetails.setRestOperationType(resourceMethod.getRestOperationType());
|
||||
|
||||
|
@ -806,6 +731,105 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
}
|
||||
|
||||
public BaseMethodBinding<?> determineResourceMethod(RequestDetails requestDetails, String requestPath) {
|
||||
RequestTypeEnum requestType = requestDetails.getRequestType();
|
||||
|
||||
ResourceBinding resourceBinding = null;
|
||||
BaseMethodBinding<?> resourceMethod = null;
|
||||
String resourceName = requestDetails.getResourceName();
|
||||
if (Constants.URL_TOKEN_METADATA.equals(resourceName) || requestType == RequestTypeEnum.OPTIONS) {
|
||||
resourceMethod = myServerConformanceMethod;
|
||||
} else if (resourceName == null) {
|
||||
resourceBinding = myServerBinding;
|
||||
} else {
|
||||
resourceBinding = myResourceNameToBinding.get(resourceName);
|
||||
if (resourceBinding == null) {
|
||||
throw new InvalidRequestException("Unknown resource type '" + resourceName + "' - Server knows how to handle: " + myResourceNameToBinding.keySet());
|
||||
}
|
||||
}
|
||||
|
||||
if (resourceMethod == null) {
|
||||
if (resourceBinding != null) {
|
||||
resourceMethod = resourceBinding.getMethod(requestDetails);
|
||||
}
|
||||
}
|
||||
if (resourceMethod == null) {
|
||||
if (isBlank(requestPath)) {
|
||||
throw new InvalidRequestException(myFhirContext.getLocalizer().getMessage(RestfulServer.class, "rootRequest"));
|
||||
} else {
|
||||
throw new InvalidRequestException(myFhirContext.getLocalizer().getMessage(RestfulServer.class, "unknownMethod", requestType.name(), requestPath, requestDetails.getParameters().keySet()));
|
||||
}
|
||||
}
|
||||
return resourceMethod;
|
||||
}
|
||||
|
||||
public void populateRequestDetailsFromRequestPath(RequestDetails theRequestDetails, String theRequestPath) {
|
||||
StringTokenizer tok = new StringTokenizer(theRequestPath, "/");
|
||||
String resourceName = null;
|
||||
|
||||
IdDt id = null;
|
||||
String operation = null;
|
||||
String compartment = null;
|
||||
if (tok.hasMoreTokens()) {
|
||||
resourceName = tok.nextToken();
|
||||
if (partIsOperation(resourceName)) {
|
||||
operation = resourceName;
|
||||
resourceName = null;
|
||||
}
|
||||
}
|
||||
theRequestDetails.setResourceName(resourceName);
|
||||
|
||||
if (tok.hasMoreTokens()) {
|
||||
String nextString = tok.nextToken();
|
||||
if (partIsOperation(nextString)) {
|
||||
operation = nextString;
|
||||
} else {
|
||||
id = new IdDt(resourceName, UrlUtil.unescape(nextString));
|
||||
}
|
||||
}
|
||||
|
||||
if (tok.hasMoreTokens()) {
|
||||
String nextString = tok.nextToken();
|
||||
if (nextString.equals(Constants.PARAM_HISTORY)) {
|
||||
if (tok.hasMoreTokens()) {
|
||||
String versionString = tok.nextToken();
|
||||
if (id == null) {
|
||||
throw new InvalidRequestException("Don't know how to handle request path: " + theRequestPath);
|
||||
}
|
||||
id = new IdDt(resourceName, id.getIdPart(), UrlUtil.unescape(versionString));
|
||||
} else {
|
||||
operation = Constants.PARAM_HISTORY;
|
||||
}
|
||||
} else if (partIsOperation(nextString)) {
|
||||
if (operation != null) {
|
||||
throw new InvalidRequestException("URL Path contains two operations: " + theRequestPath);
|
||||
}
|
||||
operation = nextString;
|
||||
} else {
|
||||
compartment = nextString;
|
||||
}
|
||||
}
|
||||
|
||||
// Secondary is for things like ..../_tags/_delete
|
||||
String secondaryOperation = null;
|
||||
|
||||
while (tok.hasMoreTokens()) {
|
||||
String nextString = tok.nextToken();
|
||||
if (operation == null) {
|
||||
operation = nextString;
|
||||
} else if (secondaryOperation == null) {
|
||||
secondaryOperation = nextString;
|
||||
} else {
|
||||
throw new InvalidRequestException("URL path has unexpected token '" + nextString + "' at the end: " + theRequestPath);
|
||||
}
|
||||
}
|
||||
|
||||
theRequestDetails.setId(id);
|
||||
theRequestDetails.setOperation(operation);
|
||||
theRequestDetails.setSecondaryOperation(secondaryOperation);
|
||||
theRequestDetails.setCompartmentName(compartment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the server. Note that this method is final to avoid accidentally introducing bugs in implementations, but subclasses may put initialization code in {@link #initialize()}, which is
|
||||
* called immediately before beginning initialization of the restful server's internal init.
|
||||
|
|
|
@ -394,8 +394,9 @@ public class RestfulServerUtils {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
public static Integer extractCountParameter(HttpServletRequest theRequest) {
|
||||
return RestfulServerUtils.tryToExtractNamedParameter(theRequest, Constants.PARAM_COUNT);
|
||||
public static Integer extractCountParameter(RequestDetails theRequest) {
|
||||
String paramName = Constants.PARAM_COUNT;
|
||||
return tryToExtractNamedParameter(theRequest, paramName);
|
||||
}
|
||||
|
||||
public static IParser getNewParser(FhirContext theContext, RequestDetails theRequestDetails) {
|
||||
|
@ -674,18 +675,18 @@ public class RestfulServerUtils {
|
|||
}
|
||||
}
|
||||
|
||||
static Integer tryToExtractNamedParameter(HttpServletRequest theRequest, String name) {
|
||||
String countString = theRequest.getParameter(name);
|
||||
Integer count = null;
|
||||
if (isNotBlank(countString)) {
|
||||
try {
|
||||
count = Integer.parseInt(countString);
|
||||
} catch (NumberFormatException e) {
|
||||
ourLog.debug("Failed to parse _count value '{}': {}", countString, e);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
// static Integer tryToExtractNamedParameter(HttpServletRequest theRequest, String name) {
|
||||
// String countString = theRequest.getParameter(name);
|
||||
// Integer count = null;
|
||||
// if (isNotBlank(countString)) {
|
||||
// try {
|
||||
// count = Integer.parseInt(countString);
|
||||
// } catch (NumberFormatException e) {
|
||||
// ourLog.debug("Failed to parse _count value '{}': {}", countString, e);
|
||||
// }
|
||||
// }
|
||||
// return count;
|
||||
// }
|
||||
|
||||
public static void validateResourceListNotNull(List<? extends IBaseResource> theResourceList) {
|
||||
if (theResourceList == null) {
|
||||
|
@ -701,4 +702,17 @@ public class RestfulServerUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static Integer tryToExtractNamedParameter(RequestDetails theRequest, String theParamName) {
|
||||
String[] retVal = theRequest.getParameters().get(theParamName);
|
||||
if (retVal == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(retVal[0]);
|
||||
} catch (NumberFormatException e) {
|
||||
ourLog.debug("Failed to parse {} value '{}': {}", new Object[] {theParamName, retVal[0], e});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -187,7 +187,7 @@ public class UrlUtil {
|
|||
char nextChar = url.charAt(idx);
|
||||
boolean atEnd = (idx + 1) == url.length();
|
||||
if (nextChar == '?' || nextChar == '/' || atEnd) {
|
||||
int endIdx = atEnd ? idx + 1 : idx;
|
||||
int endIdx = (atEnd && nextChar != '?') ? idx + 1 : idx;
|
||||
String nextSubstring = url.substring(nextStart, endIdx);
|
||||
if (retVal.getResourceType() == null) {
|
||||
retVal.setResourceType(nextSubstring);
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.validation.schematron;
|
||||
|
||||
/*
|
||||
* #%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%
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
|
|
@ -8,6 +8,7 @@ import org.apache.commons.cli.CommandLine;
|
|||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketFrame;
|
||||
|
@ -100,8 +101,12 @@ public class WebsocketSubscribeCommand extends BaseCommand {
|
|||
|
||||
@OnWebSocketFrame
|
||||
public void onFrame(Frame theFrame) {
|
||||
ourLog.info("Websocket frame: {}", theFrame);
|
||||
myQuit = true;
|
||||
ourLog.debug("Websocket frame: {}", theFrame);
|
||||
}
|
||||
|
||||
@OnWebSocketClose
|
||||
public void onClose(int statusCode, String reason) {
|
||||
ourLog.info("Received CLOSE status={} reason={}", statusCode, reason);
|
||||
}
|
||||
|
||||
@OnWebSocketConnect
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.jpa.config;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.jpa.config;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowire;
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.jpa.config;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowire;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.jpa.config;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowire;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
|
|
@ -802,22 +802,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
|
||||
public static SearchParameterMap translateMatchUrl(String theMatchUrl, RuntimeResourceDefinition resourceDef) {
|
||||
SearchParameterMap paramMap = new SearchParameterMap();
|
||||
List<NameValuePair> parameters;
|
||||
String matchUrl = theMatchUrl;
|
||||
int questionMarkIndex = matchUrl.indexOf('?');
|
||||
if (questionMarkIndex != -1) {
|
||||
matchUrl = matchUrl.substring(questionMarkIndex + 1);
|
||||
}
|
||||
matchUrl = matchUrl.replace("|", "%7C");
|
||||
matchUrl = matchUrl.replace("=>=", "=%3E%3D");
|
||||
matchUrl = matchUrl.replace("=<=", "=%3C%3D");
|
||||
matchUrl = matchUrl.replace("=>", "=%3E");
|
||||
matchUrl = matchUrl.replace("=<", "=%3C");
|
||||
if (matchUrl.contains(" ")) {
|
||||
throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - URL is invalid (must not contain spaces)");
|
||||
}
|
||||
|
||||
parameters = URLEncodedUtils.parse((matchUrl), Constants.CHARSET_UTF8, '&');
|
||||
List<NameValuePair> parameters = translateMatchUrl(theMatchUrl);
|
||||
|
||||
ArrayListMultimap<String, QualifiedParamList> nameToParamLists = ArrayListMultimap.create();
|
||||
for (NameValuePair next : parameters) {
|
||||
|
@ -891,6 +876,26 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
return paramMap;
|
||||
}
|
||||
|
||||
protected static List<NameValuePair> translateMatchUrl(String theMatchUrl) {
|
||||
List<NameValuePair> parameters;
|
||||
String matchUrl = theMatchUrl;
|
||||
int questionMarkIndex = matchUrl.indexOf('?');
|
||||
if (questionMarkIndex != -1) {
|
||||
matchUrl = matchUrl.substring(questionMarkIndex + 1);
|
||||
}
|
||||
matchUrl = matchUrl.replace("|", "%7C");
|
||||
matchUrl = matchUrl.replace("=>=", "=%3E%3D");
|
||||
matchUrl = matchUrl.replace("=<=", "=%3C%3D");
|
||||
matchUrl = matchUrl.replace("=>", "=%3E");
|
||||
matchUrl = matchUrl.replace("=<", "=%3C");
|
||||
if (matchUrl.contains(" ")) {
|
||||
throw new InvalidRequestException("Failed to parse match URL[" + theMatchUrl + "] - URL is invalid (must not contain spaces)");
|
||||
}
|
||||
|
||||
parameters = URLEncodedUtils.parse((matchUrl), Constants.CHARSET_UTF8, '&');
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDaoListener(IDaoListener theListener) {
|
||||
Validate.notNull(theListener, "theListener");
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
|
@ -44,6 +44,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntryTransactionMethodEnum;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||
|
@ -59,7 +60,7 @@ public class FhirSystemDaoDstu1 extends BaseHapiFhirSystemDao<List<IResource>> {
|
|||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
@Override
|
||||
public List<IResource> transaction(List<IResource> theResources) {
|
||||
public List<IResource> transaction(RequestDetails theRequestDetails, List<IResource> theResources) {
|
||||
ourLog.info("Beginning transaction with {} resources", theResources.size());
|
||||
|
||||
// Notify interceptors
|
||||
|
|
|
@ -23,6 +23,7 @@ import static org.apache.commons.lang3.StringUtils.defaultString;
|
|||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
|
@ -32,15 +33,19 @@ import java.util.Set;
|
|||
|
||||
import javax.persistence.TypedQuery;
|
||||
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.jpa.entity.TagDefinition;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
@ -57,13 +62,19 @@ import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum;
|
|||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.method.MethodUtil;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.BaseResourceReturningMethodBinding;
|
||||
import ca.uhn.fhir.rest.method.BaseResourceReturningMethodBinding.ResourceOrDstu1Bundle;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.NotModifiedException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
|
@ -83,12 +94,12 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
|||
return url;
|
||||
}
|
||||
|
||||
private Bundle batch(Bundle theRequest) {
|
||||
private Bundle batch(final RequestDetails theRequestDetails, Bundle theRequest) {
|
||||
ourLog.info("Beginning batch with {} resources", theRequest.getEntry().size());
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
|
||||
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
|
||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||
|
||||
Bundle resp = new Bundle();
|
||||
resp.setType(BundleTypeEnum.BATCH_RESPONSE);
|
||||
|
@ -96,8 +107,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
|||
resp.addEntry().setResource(ooResp);
|
||||
|
||||
/*
|
||||
* For batch, we handle each entry as a mini-transaction in its own database transaction so that if one fails, it
|
||||
* doesn't prevent others
|
||||
* For batch, we handle each entry as a mini-transaction in its own database transaction so that if one fails, it doesn't prevent others
|
||||
*/
|
||||
|
||||
for (final Entry nextRequestEntry : theRequest.getEntry()) {
|
||||
|
@ -109,7 +119,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
|||
subRequestBundle.setType(BundleTypeEnum.TRANSACTION);
|
||||
subRequestBundle.addEntry(nextRequestEntry);
|
||||
|
||||
Bundle subResponseBundle = transaction(subRequestBundle, "Batch sub-request");
|
||||
Bundle subResponseBundle = transaction(theRequestDetails, subRequestBundle, "Batch sub-request");
|
||||
return subResponseBundle;
|
||||
}
|
||||
};
|
||||
|
@ -122,8 +132,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
|||
Entry subResponseEntry = nextResponseBundle.getEntry().get(0);
|
||||
resp.addEntry(subResponseEntry);
|
||||
/*
|
||||
* If the individual entry didn't have a resource in its response, bring the sub-transaction's
|
||||
* OperationOutcome across so the client can see it
|
||||
* If the individual entry didn't have a resource in its response, bring the sub-transaction's OperationOutcome across so the client can see it
|
||||
*/
|
||||
if (subResponseEntry.getResource() == null) {
|
||||
subResponseEntry.setResource(nextResponseBundle.getEntry().get(0).getResource());
|
||||
|
@ -173,19 +182,19 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
|||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
@Override
|
||||
public Bundle transaction(Bundle theRequest) {
|
||||
public Bundle transaction(RequestDetails theRequestDetails, Bundle theRequest) {
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(null, "Bundle", theRequest);
|
||||
notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails);
|
||||
|
||||
String theActionName = "Transaction";
|
||||
return transaction(theRequest, theActionName);
|
||||
String actionName = "Transaction";
|
||||
return transaction(theRequestDetails, theRequest, actionName);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Bundle transaction(Bundle theRequest, String theActionName) {
|
||||
private Bundle transaction(RequestDetails theRequestDetails, Bundle theRequest, String theActionName) {
|
||||
BundleTypeEnum transactionType = theRequest.getTypeElement().getValueAsEnum();
|
||||
if (transactionType == BundleTypeEnum.BATCH) {
|
||||
return batch(theRequest);
|
||||
return batch(theRequestDetails, theRequest);
|
||||
}
|
||||
|
||||
if (transactionType == null) {
|
||||
|
@ -312,67 +321,67 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
|||
}
|
||||
case GET: {
|
||||
// SEARCH/READ/VREAD
|
||||
RequestDetails requestDetails = new RequestDetails();
|
||||
requestDetails.setServletRequest(theRequestDetails.getServletRequest());
|
||||
requestDetails.setRequestType(RequestTypeEnum.GET);
|
||||
requestDetails.setServer(theRequestDetails.getServer());
|
||||
|
||||
String url = extractTransactionUrlOrThrowException(nextEntry, verb);
|
||||
UrlParts parts = UrlUtil.parseUrl(url);
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
IFhirResourceDao dao = toDao(parts, verb.getCode(), url);
|
||||
|
||||
String ifNoneMatch = nextEntry.getRequest().getIfNoneMatch();
|
||||
if (isNotBlank(ifNoneMatch)) {
|
||||
ifNoneMatch = MethodUtil.parseETagValue(ifNoneMatch);
|
||||
int qIndex = url.indexOf('?');
|
||||
ArrayListMultimap<String, String> paramValues = ArrayListMultimap.create();
|
||||
requestDetails.setParameters(new HashMap<String, String[]>());
|
||||
if (qIndex != -1) {
|
||||
String params = url.substring(qIndex);
|
||||
List<NameValuePair> parameters = translateMatchUrl(params);
|
||||
for (NameValuePair next : parameters) {
|
||||
paramValues.put(next.getName(), next.getValue());
|
||||
}
|
||||
for (java.util.Map.Entry<String, Collection<String>> nextParamEntry : paramValues.asMap().entrySet()) {
|
||||
String[] nextValue = nextParamEntry.getValue().toArray(new String[nextParamEntry.getValue().size()]);
|
||||
requestDetails.getParameters().put(nextParamEntry.getKey(), nextValue);
|
||||
}
|
||||
url = url.substring(0, qIndex);
|
||||
}
|
||||
|
||||
if (parts.getResourceId() != null && parts.getParams() == null) {
|
||||
IResource found;
|
||||
boolean notChanged = false;
|
||||
if (parts.getVersionId() != null) {
|
||||
if (isNotBlank(ifNoneMatch)) {
|
||||
throw new InvalidRequestException("Unable to perform vread on '" + url + "' with ifNoneMatch also set. Do not include a version in the URL to perform a conditional read.");
|
||||
}
|
||||
found = (IResource) dao.read(new IdDt(parts.getResourceType(), parts.getResourceId(), parts.getVersionId()));
|
||||
} else {
|
||||
found = (IResource) dao.read(new IdDt(parts.getResourceType(), parts.getResourceId()));
|
||||
if (isNotBlank(ifNoneMatch) && ifNoneMatch.equals(found.getId().getVersionIdPart())) {
|
||||
notChanged = true;
|
||||
requestDetails.setRequestPath(url);
|
||||
requestDetails.setFhirServerBase(theRequestDetails.getFhirServerBase());
|
||||
|
||||
theRequestDetails.getServer().populateRequestDetailsFromRequestPath(requestDetails, url);
|
||||
BaseMethodBinding<?> method = theRequestDetails.getServer().determineResourceMethod(requestDetails, url);
|
||||
if (method == null) {
|
||||
throw new IllegalArgumentException("Unable to handle GET " + url);
|
||||
}
|
||||
|
||||
if (isNotBlank(nextEntry.getRequest().getIfMatch())) {
|
||||
requestDetails.addHeader(Constants.HEADER_IF_MATCH, nextEntry.getRequest().getIfMatch());
|
||||
}
|
||||
if (isNotBlank(nextEntry.getRequest().getIfNoneExist())) {
|
||||
requestDetails.addHeader(Constants.HEADER_IF_NONE_EXIST, nextEntry.getRequest().getIfNoneExist());
|
||||
}
|
||||
if (isNotBlank(nextEntry.getRequest().getIfNoneMatch())) {
|
||||
requestDetails.addHeader(Constants.HEADER_IF_NONE_MATCH, nextEntry.getRequest().getIfNoneMatch());
|
||||
}
|
||||
|
||||
if (method instanceof BaseResourceReturningMethodBinding) {
|
||||
try {
|
||||
ResourceOrDstu1Bundle responseData = ((BaseResourceReturningMethodBinding) method).invokeServer(theRequestDetails.getServer(), requestDetails, new byte[0]);
|
||||
Entry newEntry = response.addEntry();
|
||||
IBaseResource resource = responseData.getResource();
|
||||
if (paramValues.containsKey(Constants.PARAM_SUMMARY) || paramValues.containsKey(Constants.PARAM_CONTENT)) {
|
||||
resource = filterNestedBundle(requestDetails, resource);
|
||||
}
|
||||
newEntry.setResource((IResource) resource);
|
||||
newEntry.getResponse().setStatus(toStatusString(Constants.STATUS_HTTP_200_OK));
|
||||
} catch (NotModifiedException e) {
|
||||
Entry newEntry = response.addEntry();
|
||||
newEntry.getResponse().setStatus(toStatusString(Constants.STATUS_HTTP_304_NOT_MODIFIED));
|
||||
}
|
||||
Entry entry = response.addEntry();
|
||||
if (notChanged == false) {
|
||||
entry.setResource(found);
|
||||
}
|
||||
EntryResponse resp = entry.getResponse();
|
||||
resp.setLocation(found.getId().toUnqualified().getValue());
|
||||
resp.setEtag(found.getId().getVersionIdPart());
|
||||
if (!notChanged) {
|
||||
resp.setStatus(toStatusString(Constants.STATUS_HTTP_200_OK));
|
||||
} else {
|
||||
resp.setStatus(toStatusString(Constants.STATUS_HTTP_304_NOT_MODIFIED));
|
||||
}
|
||||
} else if (parts.getParams() != null) {
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(dao.getResourceType());
|
||||
SearchParameterMap params = translateMatchUrl(url, def);
|
||||
IBundleProvider bundle = dao.search(params);
|
||||
|
||||
Bundle searchBundle = new Bundle();
|
||||
searchBundle.setTotal(bundle.size());
|
||||
|
||||
int configuredMax = 200; // this should probably be configurable or something
|
||||
if (bundle.size() > configuredMax) {
|
||||
throw new InvalidRequestException("Search nested within transaction found more than " + configuredMax + " matches, but paging is not supported in nested transactions");
|
||||
}
|
||||
List<IBaseResource> resourcesToAdd = bundle.getResources(0, Math.min(bundle.size(), configuredMax));
|
||||
for (IBaseResource next : resourcesToAdd) {
|
||||
searchBundle.addEntry().setResource((IResource) next);
|
||||
}
|
||||
|
||||
Entry newEntry = response.addEntry();
|
||||
newEntry.setResource(searchBundle);
|
||||
newEntry.getResponse().setStatus(toStatusString(Constants.STATUS_HTTP_200_OK));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unable to handle GET " + url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FhirTerser terser = getContext().newTerser();
|
||||
|
@ -416,7 +425,8 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
|||
IFhirResourceDao<?> resourceDao = getDao(nextEntry.getResource().getClass());
|
||||
Set<Long> val = resourceDao.processMatchUrl(matchUrl);
|
||||
if (val.size() > 1) {
|
||||
throw new InvalidRequestException("Unable to process " + theActionName + " - Request would cause multiple resources to match URL: \"" + matchUrl + "\". Does transaction request contain duplicates?");
|
||||
throw new InvalidRequestException(
|
||||
"Unable to process " + theActionName + " - Request would cause multiple resources to match URL: \"" + matchUrl + "\". Does transaction request contain duplicates?");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -442,6 +452,20 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
|||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called for nested bundles (e.g. if we received a transaction with an entry that
|
||||
* was a GET search, this method is called on the bundle for the search result, that will be placed in the
|
||||
* outer bundle). This method applies the _summary and _content parameters to the output of
|
||||
* that bundle.
|
||||
*
|
||||
* TODO: This isn't the most efficient way of doing this.. hopefully we can come up with something better in the future.
|
||||
*/
|
||||
private IBaseResource filterNestedBundle(RequestDetails theRequestDetails, IBaseResource theResource) {
|
||||
IParser p = getContext().newJsonParser();
|
||||
RestfulServerUtils.configureResponseParser(theRequestDetails, p);
|
||||
return p.parseResource(theResource.getClass(), p.encodeResourceToString(theResource));
|
||||
}
|
||||
|
||||
private ca.uhn.fhir.jpa.dao.IFhirResourceDao<? extends IBaseResource> toDao(UrlParts theParts, String theVerb, String theUrl) {
|
||||
RuntimeResourceDefinition resType;
|
||||
try {
|
||||
|
@ -459,10 +483,10 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
|||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
|
||||
if (theParts.getResourceId() == null && theParts.getParams() == null) {
|
||||
String msg = getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionInvalidUrl", theVerb, theUrl);
|
||||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
// if (theParts.getResourceId() == null && theParts.getParams() == null) {
|
||||
// String msg = getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionInvalidUrl", theVerb, theUrl);
|
||||
// throw new InvalidRequestException(msg);
|
||||
// }
|
||||
|
||||
return dao;
|
||||
}
|
||||
|
@ -475,15 +499,15 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
private static void handleTransactionCreateOrUpdateOutcome(Map<IdDt, IdDt> idSubstitutions, Map<IdDt, DaoMethodOutcome> idToPersistedOutcome, IdDt nextResourceId, DaoMethodOutcome outcome, Entry newEntry, String theResourceType, IResource theRes) {
|
||||
private static void handleTransactionCreateOrUpdateOutcome(Map<IdDt, IdDt> idSubstitutions, Map<IdDt, DaoMethodOutcome> idToPersistedOutcome, IdDt nextResourceId, DaoMethodOutcome outcome,
|
||||
Entry newEntry, String theResourceType, IResource theRes) {
|
||||
IdDt newId = (IdDt) outcome.getId().toUnqualifiedVersionless();
|
||||
IdDt resourceId = isPlaceholder(nextResourceId) ? nextResourceId : nextResourceId.toUnqualifiedVersionless();
|
||||
if (newId.equals(resourceId) == false) {
|
||||
idSubstitutions.put(resourceId, newId);
|
||||
if (isPlaceholder(resourceId)) {
|
||||
/*
|
||||
* The correct way for substitution IDs to be is to be with no resource type, but we'll accept the qualified
|
||||
* kind too just to be lenient.
|
||||
* The correct way for substitution IDs to be is to be with no resource type, but we'll accept the qualified kind too just to be lenient.
|
||||
*/
|
||||
idSubstitutions.put(new IdDt(theResourceType + '/' + resourceId.getValue()), newId);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.util.Map;
|
|||
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
|
||||
/**
|
||||
|
@ -58,6 +59,6 @@ public interface IFhirSystemDao<T> extends IDao {
|
|||
*/
|
||||
MetaDt metaGetOperation();
|
||||
|
||||
T transaction(T theResources);
|
||||
T transaction(RequestDetails theRequestDetails, T theResources);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ISearchDao {
|
||||
|
|
|
@ -29,12 +29,23 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jboss.logging.MDC;
|
||||
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
|
||||
public class BaseJpaProvider {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseJpaProvider.class);
|
||||
public static final String REMOTE_ADDR = "req.remoteAddr";
|
||||
|
||||
public static final String REMOTE_UA = "req.userAgent";
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseJpaProvider.class);
|
||||
public void endRequest(HttpServletRequest theRequest) {
|
||||
MDC.remove(REMOTE_ADDR);
|
||||
MDC.remove(REMOTE_UA);
|
||||
}
|
||||
|
||||
public void endRequest(RequestDetails theRequest) {
|
||||
endRequest(theRequest.getServletRequest());
|
||||
}
|
||||
|
||||
public void startRequest(HttpServletRequest theRequest) {
|
||||
if (theRequest == null) {
|
||||
|
@ -49,7 +60,7 @@ public class BaseJpaProvider {
|
|||
|
||||
Enumeration<String> forwardedFors = theRequest.getHeaders("x-forwarded-for");
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (Enumeration<String> enums = forwardedFors; enums.hasMoreElements();) {
|
||||
for (Enumeration<String> enums = forwardedFors; enums != null && enums.hasMoreElements();) {
|
||||
if (b.length() > 0) {
|
||||
b.append(" / ");
|
||||
}
|
||||
|
@ -71,9 +82,8 @@ public class BaseJpaProvider {
|
|||
|
||||
}
|
||||
|
||||
public void endRequest(HttpServletRequest theRequest) {
|
||||
MDC.remove(REMOTE_ADDR);
|
||||
MDC.remove(REMOTE_UA);
|
||||
public void startRequest(RequestDetails theRequest) {
|
||||
startRequest(theRequest.getServletRequest());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,21 +22,20 @@ package ca.uhn.fhir.jpa.provider;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.rest.annotation.Transaction;
|
||||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
|
||||
public class JpaSystemProviderDstu1 extends BaseJpaSystemProvider<List<IResource>> {
|
||||
|
||||
@Transaction
|
||||
public List<IResource> transaction(HttpServletRequest theRequest, @TransactionParam List<IResource> theResources) {
|
||||
startRequest(theRequest);
|
||||
public List<IResource> transaction(RequestDetails theRequestDetails, @TransactionParam List<IResource> theResources) {
|
||||
startRequest(theRequestDetails);
|
||||
try {
|
||||
return getDao().transaction(theResources);
|
||||
return getDao().transaction(theRequestDetails, theResources);
|
||||
} finally {
|
||||
endRequest(theRequest);
|
||||
endRequest(theRequestDetails);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ import ca.uhn.fhir.rest.annotation.Operation;
|
|||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.annotation.Transaction;
|
||||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
|
||||
public class JpaSystemProviderDstu2 extends BaseJpaSystemProvider<Bundle> {
|
||||
|
||||
|
@ -182,12 +183,12 @@ public class JpaSystemProviderDstu2 extends BaseJpaSystemProvider<Bundle> {
|
|||
}
|
||||
|
||||
@Transaction
|
||||
public Bundle transaction(HttpServletRequest theRequest, @TransactionParam Bundle theResources) {
|
||||
startRequest(theRequest);
|
||||
public Bundle transaction(RequestDetails theRequestDetails, @TransactionParam Bundle theResources) {
|
||||
startRequest(theRequestDetails);
|
||||
try {
|
||||
return getDao().transaction(theResources);
|
||||
return getDao().transaction(theRequestDetails, theResources);
|
||||
} finally {
|
||||
endRequest(theRequest);
|
||||
endRequest(theRequestDetails);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.jpa.search;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
import org.hibernate.search.indexes.interceptor.EntityIndexingInterceptor;
|
||||
import org.hibernate.search.indexes.interceptor.IndexingOverride;
|
||||
|
||||
|
|
|
@ -218,7 +218,9 @@ public class SubscriptionWebsocketHandler extends TextWebSocketHandler implement
|
|||
|
||||
if (!id.hasIdPart() || !id.isIdPartValid()) {
|
||||
try {
|
||||
theSession.close(new CloseStatus(CloseStatus.PROTOCOL_ERROR.getCode(), "Invalid bind request - No ID included"));
|
||||
String message = "Invalid bind request - No ID included";
|
||||
ourLog.warn(message);
|
||||
theSession.close(new CloseStatus(CloseStatus.PROTOCOL_ERROR.getCode(), message));
|
||||
} catch (IOException e) {
|
||||
handleFailure(e);
|
||||
}
|
||||
|
@ -236,7 +238,9 @@ public class SubscriptionWebsocketHandler extends TextWebSocketHandler implement
|
|||
myState = new BoundStaticSubscipriptionState(theSession);
|
||||
} catch (ResourceNotFoundException e) {
|
||||
try {
|
||||
theSession.close(new CloseStatus(CloseStatus.PROTOCOL_ERROR.getCode(), "Invalid bind request - Unknown subscription: " + id.getValue()));
|
||||
String message = "Invalid bind request - Unknown subscription: " + id.getValue();
|
||||
ourLog.warn(message);
|
||||
theSession.close(new CloseStatus(CloseStatus.PROTOCOL_ERROR.getCode(), message));
|
||||
} catch (IOException e1) {
|
||||
handleFailure(e);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.jpa.util;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* 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%
|
||||
*/
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.apache.lucene.document.Document;
|
||||
|
|
|
@ -60,6 +60,7 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
|
|||
extraProperties.put("hibernate.format_sql", "true");
|
||||
extraProperties.put("hibernate.show_sql", "false");
|
||||
extraProperties.put("hibernate.hbm2ddl.auto", "update");
|
||||
extraProperties.put("hibernate.dialect", "org.hibernate.dialect.DerbyTenSevenDialect");
|
||||
return extraProperties;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import static org.junit.Assert.assertNotNull;
|
|||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
@ -21,10 +22,10 @@ import java.util.Map;
|
|||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.config.TestDstu1Config;
|
||||
|
@ -41,6 +42,7 @@ import ca.uhn.fhir.model.dstu.resource.Observation;
|
|||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
@ -54,6 +56,7 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest {
|
|||
private static IFhirResourceDao<Observation> ourObservationDao;
|
||||
private static IFhirResourceDao<Patient> ourPatientDao;
|
||||
private static IFhirSystemDao<List<IResource>> ourSystemDao;
|
||||
private RequestDetails myRequestDetails;
|
||||
|
||||
@Test
|
||||
public void testGetResourceCounts() {
|
||||
|
@ -140,7 +143,7 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest {
|
|||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/testPersistWithSimpleLinkP01"));
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient, obs));
|
||||
ourSystemDao.transaction(myRequestDetails, Arrays.asList((IResource) patient, obs));
|
||||
|
||||
String patientId = (patient.getId().getIdPart());
|
||||
String obsId = (obs.getId().getIdPart());
|
||||
|
@ -169,7 +172,7 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest {
|
|||
patient.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP02");
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO02");
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient, obs));
|
||||
ourSystemDao.transaction(myRequestDetails, Arrays.asList((IResource) patient, obs));
|
||||
|
||||
String patientId2 = (patient.getId().getIdPart());
|
||||
String patientVersion2 = (patient.getId().getVersionIdPart());
|
||||
|
@ -183,6 +186,11 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest {
|
|||
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
myRequestDetails = mock(RequestDetails.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistWithUnknownId() {
|
||||
Observation obs = new Observation();
|
||||
|
@ -190,7 +198,7 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest {
|
|||
obs.setSubject(new ResourceReferenceDt("Patient/999998888888"));
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) obs));
|
||||
ourSystemDao.transaction(myRequestDetails, Arrays.asList((IResource) obs));
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource Patient/999998888888 not found, specified in path: Observation.subject"));
|
||||
}
|
||||
|
@ -200,7 +208,7 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest {
|
|||
obs.setSubject(new ResourceReferenceDt("Patient/1.2.3.4"));
|
||||
|
||||
try {
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) obs));
|
||||
ourSystemDao.transaction(myRequestDetails, Arrays.asList((IResource) obs));
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource Patient/1.2.3.4 not found, specified in path: Observation.subject"));
|
||||
}
|
||||
|
@ -290,7 +298,7 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest {
|
|||
patient2.setId(new IdDt("Patient/testTransactionFailsWithDusplicateIds"));
|
||||
patient2.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP02");
|
||||
|
||||
ourSystemDao.transaction(Arrays.asList((IResource) patient1, patient2));
|
||||
ourSystemDao.transaction(myRequestDetails, Arrays.asList((IResource) patient1, patient2));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -300,7 +308,7 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest {
|
|||
Bundle bundle = ourFhirContext.newXmlParser().parseBundle(new InputStreamReader(bundleRes));
|
||||
List<IResource> res = bundle.toListOfResources();
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
ourSystemDao.transaction(myRequestDetails, res);
|
||||
|
||||
Patient p1 = (Patient) res.get(0);
|
||||
String id = p1.getId().getValue();
|
||||
|
@ -333,7 +341,7 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest {
|
|||
o2.setSubject(new ResourceReferenceDt("Patient/cid:patient1"));
|
||||
res.add(o2);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
ourSystemDao.transaction(myRequestDetails, res);
|
||||
|
||||
assertTrue(p1.getId().getValue(), p1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
assertTrue(o1.getId().getValue(), o1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
|
@ -355,7 +363,7 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest {
|
|||
res.add(next.getResource());
|
||||
}
|
||||
|
||||
List<IResource> response = ourSystemDao.transaction(res);
|
||||
List<IResource> response = ourSystemDao.transaction(myRequestDetails, res);
|
||||
|
||||
String encodeResourceToString = ourFhirContext.newXmlParser().setPrettyPrint(true).encodeResourceToString(response.get(0));
|
||||
ourLog.info(encodeResourceToString);
|
||||
|
@ -388,7 +396,7 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest {
|
|||
o2.setSubject(new ResourceReferenceDt("cid:patient1"));
|
||||
res.add(o2);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
ourSystemDao.transaction(myRequestDetails, res);
|
||||
|
||||
assertTrue(p1.getId().getValue(), p1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
assertTrue(o1.getId().getValue(), o1.getId().getIdPart().matches("^[0-9]+$"));
|
||||
|
@ -421,7 +429,7 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest {
|
|||
p3.addIdentifier().setSystem("urn:system").setValue("testTransactionWithDelete");
|
||||
res.add(p3);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
ourSystemDao.transaction(myRequestDetails, res);
|
||||
|
||||
/*
|
||||
* Verify
|
||||
|
@ -447,7 +455,7 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest {
|
|||
ResourceMetadataKeyEnum.DELETED_AT.put(p2, InstantDt.withCurrentTime());
|
||||
res.add(p2);
|
||||
|
||||
ourSystemDao.transaction(res);
|
||||
ourSystemDao.transaction(myRequestDetails, res);
|
||||
|
||||
/*
|
||||
* Verify
|
||||
|
|
|
@ -14,28 +14,36 @@ import static org.junit.Assert.assertThat;
|
|||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceEncodingEnum;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
|
||||
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
|
||||
import ca.uhn.fhir.jpa.rp.dstu2.PatientResourceProvider;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
|
@ -47,7 +55,6 @@ import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
|||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.EntryRequest;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.EntryResponse;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Communication;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Medication;
|
||||
import ca.uhn.fhir.model.dstu2.resource.MedicationOrder;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
|
@ -58,11 +65,13 @@ import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum;
|
|||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
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.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||
|
@ -72,15 +81,27 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetai
|
|||
public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoDstu2Test.class);
|
||||
private RequestDetails myRequestDetails;
|
||||
private RestfulServer myServer;
|
||||
|
||||
@Test
|
||||
public void testTransactionFromBundle6() throws Exception {
|
||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/simone_bundle3.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
Bundle output = mySystemDao.transaction(myFhirCtx.newXmlParser().parseResource(Bundle.class, bundle));
|
||||
Bundle output = mySystemDao.transaction(myRequestDetails, myFhirCtx.newXmlParser().parseResource(Bundle.class, bundle));
|
||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNestedCount() {
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("family");
|
||||
final IIdType id = myPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRendexing() {
|
||||
Patient p = new Patient();
|
||||
|
@ -262,7 +283,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
o.getSubject().setReference("Patient/" + methodName);
|
||||
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Bundle resp = mySystemDao.transaction(request);
|
||||
Bundle resp = mySystemDao.transaction(myRequestDetails, request);
|
||||
assertEquals(2, resp.getEntry().size());
|
||||
|
||||
Entry respEntry = resp.getEntry().get(0);
|
||||
|
@ -290,7 +311,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
try {
|
||||
mySystemDao.transaction(request);
|
||||
mySystemDao.transaction(myRequestDetails, request);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Unable to process transaction where incoming Bundle.type = searchset", e.getMessage());
|
||||
|
@ -298,6 +319,27 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Before
|
||||
public void before() throws ServletException {
|
||||
myRequestDetails = mock(RequestDetails.class);
|
||||
|
||||
if (myServer == null) {
|
||||
myServer = new RestfulServer(myFhirCtx);
|
||||
|
||||
PatientResourceProvider patientRp = new PatientResourceProvider();
|
||||
patientRp.setDao(myPatientDao);
|
||||
myServer.setResourceProviders(patientRp);
|
||||
myServer.init(mock(ServletConfig.class));
|
||||
}
|
||||
|
||||
when(myRequestDetails.getServer()).thenReturn(myServer);
|
||||
HttpServletRequest servletRequest = mock(HttpServletRequest.class);
|
||||
when(myRequestDetails.getServletRequest()).thenReturn(servletRequest);
|
||||
when(servletRequest.getHeaderNames()).thenReturn(mock(Enumeration.class));
|
||||
when(servletRequest.getRequestURL()).thenReturn(new StringBuffer("/Patient"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionSingleEmptyResource() {
|
||||
|
||||
|
@ -307,7 +349,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
try {
|
||||
mySystemDao.transaction(request);
|
||||
mySystemDao.transaction(myRequestDetails, request);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Unable to process transaction where incoming Bundle.type = searchset", e.getMessage());
|
||||
|
@ -327,7 +369,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
|
||||
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient/THIS_ID_DOESNT_EXIST");
|
||||
|
||||
Bundle resp = mySystemDao.transaction(request);
|
||||
Bundle resp = mySystemDao.transaction(myRequestDetails, request);
|
||||
assertEquals(3, resp.getEntry().size());
|
||||
assertEquals(BundleTypeEnum.BATCH_RESPONSE, resp.getTypeElement().getValueAsEnum());
|
||||
|
||||
|
@ -377,7 +419,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
try {
|
||||
mySystemDao.transaction(request);
|
||||
mySystemDao.transaction(myRequestDetails, request);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals(e.getMessage(),
|
||||
|
@ -397,7 +439,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
|
||||
try {
|
||||
entry.setIfNoneExist("Patient?identifier identifier" + methodName);
|
||||
mySystemDao.transaction(request);
|
||||
mySystemDao.transaction(myRequestDetails, request);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Failed to parse match URL[Patient?identifier identifiertestTransactionCreateWithInvalidMatchUrl] - URL is invalid (must not contain spaces)", e.getMessage());
|
||||
|
@ -405,7 +447,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
|
||||
try {
|
||||
entry.setIfNoneExist("Patient?identifier=");
|
||||
mySystemDao.transaction(request);
|
||||
mySystemDao.transaction(myRequestDetails, request);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Invalid match URL[Patient?identifier=] - URL has no search parameters", e.getMessage());
|
||||
|
@ -413,7 +455,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
|
||||
try {
|
||||
entry.setIfNoneExist("Patient?foo=bar");
|
||||
mySystemDao.transaction(request);
|
||||
mySystemDao.transaction(myRequestDetails, request);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Failed to parse match URL[Patient?foo=bar] - Resource type Patient does not have a parameter with name: foo", e.getMessage());
|
||||
|
@ -435,7 +477,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
try {
|
||||
mySystemDao.transaction(request);
|
||||
mySystemDao.transaction(myRequestDetails, request);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals(e.getMessage(),
|
||||
|
@ -470,7 +512,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
try {
|
||||
mySystemDao.transaction(request);
|
||||
mySystemDao.transaction(myRequestDetails, request);
|
||||
fail();
|
||||
} catch (PreconditionFailedException e) {
|
||||
assertThat(e.getMessage(), containsString("with match URL \"Patient"));
|
||||
|
@ -493,7 +535,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
o.getSubject().setReference("Patient/" + methodName);
|
||||
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Bundle resp = mySystemDao.transaction(request);
|
||||
Bundle resp = mySystemDao.transaction(myRequestDetails, request);
|
||||
assertEquals(BundleTypeEnum.TRANSACTION_RESPONSE, resp.getTypeElement().getValueAsEnum());
|
||||
assertEquals(2, resp.getEntry().size());
|
||||
|
||||
|
@ -525,7 +567,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
p.setId("Patient/" + methodName);
|
||||
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Bundle resp = mySystemDao.transaction(request);
|
||||
Bundle resp = mySystemDao.transaction(myRequestDetails, request);
|
||||
assertEquals(1, resp.getEntry().size());
|
||||
|
||||
Entry respEntry = resp.getEntry().get(0);
|
||||
|
@ -564,7 +606,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
try {
|
||||
mySystemDao.transaction(request);
|
||||
mySystemDao.transaction(myRequestDetails, request);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource Organization/9999999999999999 not found, specified in path: Patient.managingOrganization"));
|
||||
|
@ -583,7 +625,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
try {
|
||||
mySystemDao.transaction(request);
|
||||
mySystemDao.transaction(myRequestDetails, request);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource Organization/" + methodName + " not found, specified in path: Patient.managingOrganization"));
|
||||
|
@ -613,7 +655,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
myPatientDao.read(id1.toVersionless());
|
||||
myPatientDao.read(id2.toVersionless());
|
||||
|
||||
Bundle resp = mySystemDao.transaction(request);
|
||||
Bundle resp = mySystemDao.transaction(myRequestDetails, request);
|
||||
|
||||
assertEquals(2, resp.getEntry().size());
|
||||
assertEquals("204 No Content", resp.getEntry().get(0).getResponse().getStatus());
|
||||
|
@ -647,7 +689,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
Bundle request = new Bundle();
|
||||
request.addEntry().getRequest().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Bundle resp = mySystemDao.transaction(request);
|
||||
Bundle resp = mySystemDao.transaction(myRequestDetails, request);
|
||||
assertEquals(1, resp.getEntry().size());
|
||||
|
||||
Entry nextEntry = resp.getEntry().get(0);
|
||||
|
@ -701,7 +743,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
request.addEntry().getRequest().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
try {
|
||||
mySystemDao.transaction(request);
|
||||
mySystemDao.transaction(myRequestDetails, request);
|
||||
fail();
|
||||
} catch (PreconditionFailedException e) {
|
||||
assertThat(e.getMessage(), containsString("resource with match URL \"Patient?"));
|
||||
|
@ -716,7 +758,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
request.addEntry().getRequest().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
// try {
|
||||
mySystemDao.transaction(request);
|
||||
mySystemDao.transaction(myRequestDetails, request);
|
||||
// fail();
|
||||
// } catch (ResourceNotFoundException e) {
|
||||
// assertThat(e.getMessage(), containsString("resource matching URL \"Patient?"));
|
||||
|
@ -736,7 +778,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
Bundle request = new Bundle();
|
||||
request.addEntry().getRequest().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Bundle res = mySystemDao.transaction(request);
|
||||
Bundle res = mySystemDao.transaction(myRequestDetails, request);
|
||||
assertEquals(1, res.getEntry().size());
|
||||
|
||||
assertEquals(Constants.STATUS_HTTP_204_NO_CONTENT + " No Content", res.getEntry().get(0).getResponse().getStatus());
|
||||
|
@ -763,7 +805,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
patient2.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP02");
|
||||
request.addEntry().setResource(patient2).getRequest().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
mySystemDao.transaction(request);
|
||||
mySystemDao.transaction(myRequestDetails, request);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -773,7 +815,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
String bundleStr = IOUtils.toString(bundleRes);
|
||||
Bundle bundle = myFhirCtx.newXmlParser().parseResource(Bundle.class, bundleStr);
|
||||
|
||||
Bundle resp = mySystemDao.transaction(bundle);
|
||||
Bundle resp = mySystemDao.transaction(myRequestDetails, bundle);
|
||||
|
||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resp));
|
||||
|
||||
|
@ -792,7 +834,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
String bundleStr = IOUtils.toString(bundleRes);
|
||||
Bundle bundle = myFhirCtx.newJsonParser().parseResource(Bundle.class, bundleStr);
|
||||
|
||||
Bundle resp = mySystemDao.transaction(bundle);
|
||||
Bundle resp = mySystemDao.transaction(myRequestDetails, bundle);
|
||||
|
||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resp));
|
||||
|
||||
|
@ -817,7 +859,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
|
||||
ourLog.info("Request:\n"+myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle));
|
||||
|
||||
Bundle outcome = mySystemDao.transaction(bundle);
|
||||
Bundle outcome = mySystemDao.transaction(myRequestDetails, bundle);
|
||||
ourLog.info("Response:\n"+myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome));
|
||||
|
||||
IdDt medId1 = new IdDt(outcome.getEntry().get(0).getResponse().getLocation());
|
||||
|
@ -839,7 +881,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
mo.setMedication(new ResourceReferenceDt(medId));
|
||||
bundle.addEntry().setResource(mo).setFullUrl(mo.getId().getValue()).getRequest().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
outcome = mySystemDao.transaction(bundle);
|
||||
outcome = mySystemDao.transaction(myRequestDetails, bundle);
|
||||
|
||||
IdDt medId2 = new IdDt(outcome.getEntry().get(0).getResponse().getLocation());
|
||||
IdDt medOrderId2 = new IdDt(outcome.getEntry().get(1).getResponse().getLocation());
|
||||
|
@ -875,7 +917,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualified().getValue());
|
||||
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
|
||||
|
||||
Bundle resp = mySystemDao.transaction(request);
|
||||
Bundle resp = mySystemDao.transaction(myRequestDetails, request);
|
||||
|
||||
assertEquals(3, resp.getEntry().size());
|
||||
|
||||
|
@ -943,7 +985,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
|
||||
Bundle request = new Bundle();
|
||||
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient?" + Constants.PARAM_COUNT + "=1");
|
||||
Bundle resp = mySystemDao.transaction(request);
|
||||
Bundle resp = mySystemDao.transaction(myRequestDetails, request);
|
||||
|
||||
assertEquals(1, resp.getEntry().size());
|
||||
|
||||
|
@ -957,7 +999,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
request = new Bundle();
|
||||
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient?" + Constants.PARAM_COUNT + "=GKJGKJG");
|
||||
try {
|
||||
mySystemDao.transaction(request);
|
||||
mySystemDao.transaction(myRequestDetails, request);
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals(e.getMessage(), ("Invalid _count value: GKJGKJG"));
|
||||
}
|
||||
|
@ -966,7 +1008,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
|
||||
request = new Bundle();
|
||||
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient?" + Constants.PARAM_COUNT + "=");
|
||||
respBundle = mySystemDao.transaction(request);
|
||||
respBundle = mySystemDao.transaction(myRequestDetails, request);
|
||||
assertThat(respBundle.getEntry().size(), greaterThan(0));
|
||||
}
|
||||
|
||||
|
@ -992,7 +1034,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue()).setIfNoneMatch("W/\"" + idv1.getVersionIdPart() + "\"");
|
||||
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue()).setIfNoneMatch("W/\"" + idv2.getVersionIdPart() + "\"");
|
||||
|
||||
Bundle resp = mySystemDao.transaction(request);
|
||||
Bundle resp = mySystemDao.transaction(myRequestDetails, request);
|
||||
|
||||
assertEquals(3, resp.getEntry().size());
|
||||
|
||||
|
@ -1011,8 +1053,8 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
assertEquals("200 OK", nextEntry.getResponse().getStatus());
|
||||
|
||||
nextEntry = resp.getEntry().get(2);
|
||||
assertNull(nextEntry.getResource());
|
||||
assertEquals("304 Not Modified", nextEntry.getResponse().getStatus());
|
||||
assertNull(nextEntry.getResource());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1036,7 +1078,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
o.getSubject().setReference("Patient/" + methodName);
|
||||
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Bundle resp = mySystemDao.transaction(request);
|
||||
Bundle resp = mySystemDao.transaction(myRequestDetails, request);
|
||||
assertEquals(2, resp.getEntry().size());
|
||||
|
||||
Entry nextEntry = resp.getEntry().get(0);
|
||||
|
@ -1083,7 +1125,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
try {
|
||||
mySystemDao.transaction(request);
|
||||
mySystemDao.transaction(myRequestDetails, request);
|
||||
fail();
|
||||
} catch (PreconditionFailedException e) {
|
||||
assertThat(e.getMessage(), containsString("with match URL \"Patient"));
|
||||
|
@ -1110,7 +1152,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
o.getSubject().setReference("Patient/" + methodName);
|
||||
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Bundle resp = mySystemDao.transaction(request);
|
||||
Bundle resp = mySystemDao.transaction(myRequestDetails, request);
|
||||
assertEquals(2, resp.getEntry().size());
|
||||
|
||||
Entry nextEntry = resp.getEntry().get(0);
|
||||
|
@ -1150,7 +1192,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
o.getSubject().setReference("Patient/" + methodName);
|
||||
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerbEnum.POST);
|
||||
|
||||
Bundle resp = mySystemDao.transaction(request);
|
||||
Bundle resp = mySystemDao.transaction(myRequestDetails, request);
|
||||
assertEquals(2, resp.getEntry().size());
|
||||
|
||||
Entry nextEntry = resp.getEntry().get(0);
|
||||
|
@ -1293,7 +1335,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
o2.setSubject(new ResourceReferenceDt("urn:oid:0.1.2.3"));
|
||||
res.addEntry().setResource(o2).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Observation");
|
||||
|
||||
Bundle resp = mySystemDao.transaction(res);
|
||||
Bundle resp = mySystemDao.transaction(myRequestDetails, res);
|
||||
|
||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
||||
|
||||
|
@ -1336,7 +1378,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
o2.setSubject(new ResourceReferenceDt("Patient/urn:oid:0.1.2.3"));
|
||||
res.addEntry().setResource(o2).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Observation");
|
||||
|
||||
Bundle resp = mySystemDao.transaction(res);
|
||||
Bundle resp = mySystemDao.transaction(myRequestDetails, res);
|
||||
|
||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
||||
|
||||
|
@ -1355,22 +1397,4 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
}
|
||||
|
||||
|
||||
static void doDeleteEverything(IFhirSystemDao<Bundle> systemDao) {
|
||||
IBundleProvider all = systemDao.history(null);
|
||||
List<IBaseResource> allRes = all.getResources(0, all.size());
|
||||
for (IBaseResource iResource : allRes) {
|
||||
if (ResourceMetadataKeyEnum.DELETED_AT.get((IResource) iResource) == null) {
|
||||
ourLog.info("Deleting: {}", iResource.getIdElement());
|
||||
|
||||
Bundle b = new Bundle();
|
||||
b.setType(BundleTypeEnum.TRANSACTION);
|
||||
String url = iResource.getIdElement().toVersionless().getValue();
|
||||
b.addEntry().getRequest().setMethod(HTTPVerbEnum.DELETE).setUrl(url);
|
||||
systemDao.transaction(b);
|
||||
}
|
||||
}
|
||||
|
||||
systemDao.deleteAllTagsOnServer();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,7 +2,12 @@ package ca.uhn.fhir.jpa.provider;
|
|||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -16,29 +21,22 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
|||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.config.TestDstu1Config;
|
||||
import ca.uhn.fhir.jpa.config.TestDstu2Config;
|
||||
import ca.uhn.fhir.jpa.dao.BaseJpaTest;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.dao.BaseJpaDstu2Test;
|
||||
import ca.uhn.fhir.jpa.rp.dstu2.ObservationResourceProvider;
|
||||
import ca.uhn.fhir.jpa.rp.dstu2.OrganizationResourceProvider;
|
||||
import ca.uhn.fhir.jpa.rp.dstu2.PatientResourceProvider;
|
||||
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.OperationDefinition;
|
||||
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
|
@ -46,36 +44,74 @@ import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
|||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||
import net.sf.saxon.lib.OutputURIResolver;
|
||||
|
||||
public class SystemProviderDstu2Test extends BaseJpaTest {
|
||||
public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
|
||||
|
||||
private static RestfulServer myRestServer;
|
||||
private static IGenericClient ourClient;
|
||||
private static FhirContext ourCtx;
|
||||
private static CloseableHttpClient ourHttpClient;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SystemProviderDstu2Test.class);
|
||||
private static Server ourServer;
|
||||
private static AnnotationConfigApplicationContext ourAppCtx;
|
||||
private static FhirContext ourCtx;
|
||||
private static IGenericClient ourClient;
|
||||
private static String ourServerBase;
|
||||
private static CloseableHttpClient ourHttpClient;
|
||||
private static RestfulServer restServer;
|
||||
|
||||
@Test
|
||||
public void testEverythingType() throws Exception {
|
||||
HttpGet get = new HttpGet(ourServerBase + "/Patient/$everything");
|
||||
CloseableHttpResponse http = ourHttpClient.execute(get);
|
||||
try {
|
||||
assertEquals(200, http.getStatusLine().getStatusCode());
|
||||
} finally {
|
||||
http.close();
|
||||
@Before
|
||||
public void beforeStartServer() throws Exception {
|
||||
if (myRestServer == null) {
|
||||
PatientResourceProvider patientRp = new PatientResourceProvider();
|
||||
patientRp.setDao(myPatientDao);
|
||||
|
||||
QuestionnaireResourceProviderDstu2 questionnaireRp = new QuestionnaireResourceProviderDstu2();
|
||||
questionnaireRp.setDao(myQuestionnaireDao);
|
||||
|
||||
ObservationResourceProvider observationRp = new ObservationResourceProvider();
|
||||
observationRp.setDao(myObservationDao);
|
||||
|
||||
OrganizationResourceProvider organizationRp = new OrganizationResourceProvider();
|
||||
organizationRp.setDao(myOrganizationDao);
|
||||
|
||||
RestfulServer restServer = new RestfulServer(ourCtx);
|
||||
restServer.setPagingProvider(new FifoMemoryPagingProvider(10).setDefaultPageSize(10));
|
||||
restServer.setResourceProviders(patientRp, questionnaireRp, observationRp, organizationRp);
|
||||
|
||||
restServer.setPlainProviders(mySystemProvider);
|
||||
|
||||
int myPort = RandomServerPortProvider.findFreePort();
|
||||
ourServer = new Server(myPort);
|
||||
|
||||
ServletContextHandler proxyHandler = new ServletContextHandler();
|
||||
proxyHandler.setContextPath("/");
|
||||
|
||||
ourServerBase = "http://localhost:" + myPort + "/fhir/context";
|
||||
|
||||
ServletHolder servletHolder = new ServletHolder();
|
||||
servletHolder.setServlet(restServer);
|
||||
proxyHandler.addServlet(servletHolder, "/fhir/context/*");
|
||||
|
||||
ourCtx = FhirContext.forDstu2();
|
||||
restServer.setFhirContext(ourCtx);
|
||||
|
||||
ourServer.setHandler(proxyHandler);
|
||||
ourServer.start();
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
builder.setConnectionManager(connectionManager);
|
||||
ourHttpClient = builder.build();
|
||||
|
||||
ourCtx.getRestfulClientFactory().setSocketTimeout(600 * 1000);
|
||||
ourClient = ourCtx.newRestfulGenericClient(ourServerBase);
|
||||
ourClient.setLogRequestAndResponse(true);
|
||||
myRestServer = restServer;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEverythingReturnsCorrectFormatInPagingLink() throws Exception {
|
||||
restServer.setDefaultResponseEncoding(EncodingEnum.JSON);
|
||||
restServer.setPagingProvider(new FifoMemoryPagingProvider(1).setDefaultPageSize(10));
|
||||
myRestServer.setDefaultResponseEncoding(EncodingEnum.JSON);
|
||||
myRestServer.setPagingProvider(new FifoMemoryPagingProvider(1).setDefaultPageSize(10));
|
||||
ResponseHighlighterInterceptor interceptor = new ResponseHighlighterInterceptor();
|
||||
restServer.registerInterceptor(interceptor);
|
||||
myRestServer.registerInterceptor(interceptor);
|
||||
|
||||
for (int i = 0; i < 11; i++) {
|
||||
Patient p = new Patient();
|
||||
|
@ -95,50 +131,24 @@ public class SystemProviderDstu2Test extends BaseJpaTest {
|
|||
http.close();
|
||||
}
|
||||
|
||||
restServer.unregisterInterceptor(interceptor);
|
||||
myRestServer.unregisterInterceptor(interceptor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionFromBundle4() throws Exception {
|
||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/simone_bundle.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
String response = ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
ourLog.info(response);
|
||||
Bundle bundleResp = ourCtx.newXmlParser().parseResource(Bundle.class, response);
|
||||
IdDt id = new IdDt(bundleResp.getEntry().get(0).getResponse().getLocation());
|
||||
assertEquals("Patient", id.getResourceType());
|
||||
assertTrue(id.hasIdPart());
|
||||
assertTrue(id.isIdPartValidLong());
|
||||
assertTrue(id.hasVersionIdPart());
|
||||
assertTrue(id.isVersionIdPartValidLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionFromBundle5() throws Exception {
|
||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/simone_bundle2.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
public void testEverythingType() throws Exception {
|
||||
HttpGet get = new HttpGet(ourServerBase + "/Patient/$everything");
|
||||
CloseableHttpResponse http = ourHttpClient.execute(get);
|
||||
try {
|
||||
ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
OperationOutcome oo = (OperationOutcome) e.getOperationOutcome();
|
||||
assertEquals("Invalid placeholder ID found: uri:uuid:bb0cd4bc-1839-4606-8c46-ba3069e69b1d - Must be of the form 'urn:uuid:[uuid]' or 'urn:oid:[oid]'", oo.getIssue().get(0).getDiagnostics());
|
||||
assertEquals("processing", oo.getIssue().get(0).getCode());
|
||||
assertEquals(200, http.getStatusLine().getStatusCode());
|
||||
} finally {
|
||||
http.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionFromBundle6() throws Exception {
|
||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/simone_bundle3.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
// try {
|
||||
// fail();
|
||||
// } catch (InvalidRequestException e) {
|
||||
// OperationOutcome oo = (OperationOutcome) e.getOperationOutcome();
|
||||
// assertEquals("Invalid placeholder ID found: uri:uuid:bb0cd4bc-1839-4606-8c46-ba3069e69b1d - Must be of the form 'urn:uuid:[uuid]' or 'urn:oid:[oid]'", oo.getIssue().get(0).getDiagnostics());
|
||||
// assertEquals("processing", oo.getIssue().get(0).getCode());
|
||||
// }
|
||||
public void testGetOperationDefinition() {
|
||||
OperationDefinition op = ourClient.read(OperationDefinition.class, "get-resource-counts");
|
||||
assertEquals("$get-resource-counts", op.getCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -149,24 +159,6 @@ public class SystemProviderDstu2Test extends BaseJpaTest {
|
|||
ourLog.info(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is Gramahe's test transaction - it requires some set up in order to work
|
||||
*/
|
||||
// @Test
|
||||
public void testTransactionFromBundle3() throws Exception {
|
||||
|
||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/grahame-transaction.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
String response = ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
ourLog.info(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOperationDefinition() {
|
||||
OperationDefinition op = ourClient.read(OperationDefinition.class, "get-resource-counts");
|
||||
assertEquals("$get-resource-counts", op.getCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionFromBundle2() throws Exception {
|
||||
|
||||
|
@ -204,65 +196,108 @@ public class SystemProviderDstu2Test extends BaseJpaTest {
|
|||
assertEquals(id1_4.toVersionless(), id2_4.toVersionless());
|
||||
}
|
||||
|
||||
/**
|
||||
* This is Gramahe's test transaction - it requires some set up in order to work
|
||||
*/
|
||||
// @Test
|
||||
public void testTransactionFromBundle3() throws Exception {
|
||||
|
||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/grahame-transaction.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
String response = ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
ourLog.info(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionFromBundle4() throws Exception {
|
||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/simone_bundle.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
String response = ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
ourLog.info(response);
|
||||
Bundle bundleResp = ourCtx.newXmlParser().parseResource(Bundle.class, response);
|
||||
IdDt id = new IdDt(bundleResp.getEntry().get(0).getResponse().getLocation());
|
||||
assertEquals("Patient", id.getResourceType());
|
||||
assertTrue(id.hasIdPart());
|
||||
assertTrue(id.isIdPartValidLong());
|
||||
assertTrue(id.hasVersionIdPart());
|
||||
assertTrue(id.isVersionIdPartValidLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionFromBundle5() throws Exception {
|
||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/simone_bundle2.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
try {
|
||||
ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
OperationOutcome oo = (OperationOutcome) e.getOperationOutcome();
|
||||
assertEquals("Invalid placeholder ID found: uri:uuid:bb0cd4bc-1839-4606-8c46-ba3069e69b1d - Must be of the form 'urn:uuid:[uuid]' or 'urn:oid:[oid]'", oo.getIssue().get(0).getDiagnostics());
|
||||
assertEquals("processing", oo.getIssue().get(0).getCode());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionFromBundle6() throws Exception {
|
||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/simone_bundle3.xml");
|
||||
String bundle = IOUtils.toString(bundleRes);
|
||||
ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||
// try {
|
||||
// fail();
|
||||
// } catch (InvalidRequestException e) {
|
||||
// OperationOutcome oo = (OperationOutcome) e.getOperationOutcome();
|
||||
// assertEquals("Invalid placeholder ID found: uri:uuid:bb0cd4bc-1839-4606-8c46-ba3069e69b1d - Must be of the form 'urn:uuid:[uuid]' or 'urn:oid:[oid]'", oo.getIssue().get(0).getDiagnostics());
|
||||
// assertEquals("processing", oo.getIssue().get(0).getCode());
|
||||
// }
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionSearch() throws Exception {
|
||||
for (int i = 0; i < 20; i ++) {
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("PATIENT_" + i);
|
||||
myPatientDao.create(p);
|
||||
}
|
||||
|
||||
Bundle req = new Bundle();
|
||||
req.setType(BundleTypeEnum.TRANSACTION);
|
||||
req.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient?");
|
||||
Bundle resp = ourClient.transaction().withBundle(req).execute();
|
||||
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
||||
|
||||
assertEquals(1, resp.getEntry().size());
|
||||
Bundle respSub = (Bundle)resp.getEntry().get(0).getResource();
|
||||
assertEquals("self", respSub.getLink().get(0).getRelation());
|
||||
assertEquals(ourServerBase + "/Patient", respSub.getLink().get(0).getUrl());
|
||||
assertEquals("next", respSub.getLink().get(1).getRelation());
|
||||
assertThat(respSub.getLink().get(1).getUrl(), containsString("/fhir/context?_getpages"));
|
||||
assertThat(respSub.getEntry().get(0).getFullUrl(), startsWith(ourServerBase + "/Patient/"));
|
||||
assertEquals(Patient.class, respSub.getEntry().get(0).getResource().getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionCount() throws Exception {
|
||||
for (int i = 0; i < 20; i ++) {
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("PATIENT_" + i);
|
||||
myPatientDao.create(p);
|
||||
}
|
||||
|
||||
Bundle req = new Bundle();
|
||||
req.setType(BundleTypeEnum.TRANSACTION);
|
||||
req.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient?_summary=count");
|
||||
Bundle resp = ourClient.transaction().withBundle(req).execute();
|
||||
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
|
||||
|
||||
assertEquals(1, resp.getEntry().size());
|
||||
Bundle respSub = (Bundle)resp.getEntry().get(0).getResource();
|
||||
assertEquals(20, respSub.getTotal().intValue());
|
||||
assertEquals(0, respSub.getEntry().size());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
ourServer.stop();
|
||||
ourAppCtx.stop();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
ourAppCtx = new AnnotationConfigApplicationContext(TestDstu2Config.class);
|
||||
|
||||
IFhirResourceDao<Patient> patientDao = (IFhirResourceDao<Patient>) ourAppCtx.getBean("myPatientDaoDstu2", IFhirResourceDao.class);
|
||||
PatientResourceProvider patientRp = new PatientResourceProvider();
|
||||
patientRp.setDao(patientDao);
|
||||
|
||||
IFhirResourceDao<Questionnaire> questionnaireDao = (IFhirResourceDao<Questionnaire>) ourAppCtx.getBean("myQuestionnaireDaoDstu2", IFhirResourceDao.class);
|
||||
QuestionnaireResourceProviderDstu2 questionnaireRp = new QuestionnaireResourceProviderDstu2();
|
||||
questionnaireRp.setDao(questionnaireDao);
|
||||
|
||||
IFhirResourceDao<Observation> observationDao = (IFhirResourceDao<Observation>) ourAppCtx.getBean("myObservationDaoDstu2", IFhirResourceDao.class);
|
||||
ObservationResourceProvider observationRp = new ObservationResourceProvider();
|
||||
observationRp.setDao(observationDao);
|
||||
|
||||
IFhirResourceDao<Organization> organizationDao = (IFhirResourceDao<Organization>) ourAppCtx.getBean("myOrganizationDaoDstu2", IFhirResourceDao.class);
|
||||
OrganizationResourceProvider organizationRp = new OrganizationResourceProvider();
|
||||
organizationRp.setDao(organizationDao);
|
||||
|
||||
restServer = new RestfulServer(ourCtx);
|
||||
restServer.setResourceProviders(patientRp, questionnaireRp, observationRp, organizationRp);
|
||||
|
||||
JpaSystemProviderDstu2 systemProv = ourAppCtx.getBean(JpaSystemProviderDstu2.class, "mySystemProviderDstu2");
|
||||
restServer.setPlainProviders(systemProv);
|
||||
|
||||
int myPort = RandomServerPortProvider.findFreePort();
|
||||
ourServer = new Server(myPort);
|
||||
|
||||
ServletContextHandler proxyHandler = new ServletContextHandler();
|
||||
proxyHandler.setContextPath("/");
|
||||
|
||||
ourServerBase = "http://localhost:" + myPort + "/fhir/context";
|
||||
|
||||
ServletHolder servletHolder = new ServletHolder();
|
||||
servletHolder.setServlet(restServer);
|
||||
proxyHandler.addServlet(servletHolder, "/fhir/context/*");
|
||||
|
||||
ourCtx = FhirContext.forDstu2();
|
||||
restServer.setFhirContext(ourCtx);
|
||||
|
||||
ourServer.setHandler(proxyHandler);
|
||||
ourServer.start();
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
builder.setConnectionManager(connectionManager);
|
||||
ourHttpClient = builder.build();
|
||||
|
||||
ourCtx.getRestfulClientFactory().setSocketTimeout(600 * 1000);
|
||||
ourClient = ourCtx.newRestfulGenericClient(ourServerBase);
|
||||
ourClient.setLogRequestAndResponse(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:security="http://www.springframework.org/schema/security"
|
||||
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
|
||||
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
|
||||
|
||||
<context:annotation-config />
|
||||
<context:mbean-server />
|
||||
|
||||
<bean depends-on="dbServer" id="myPersistenceDataSourceDstu1" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
|
||||
<!-- ;create=true /opt/glassfish/glassfish4/glassfish/nodes/localhost-domain1/fhirtest/fhirdb -->
|
||||
<!-- <property name="url" value="jdbc:hsqldb:hsql://localhost/uhnfhirdb"/>-->
|
||||
<!-- <property name="url" value="jdbc:derby:directory:#{systemproperties['fhir.db.location']};create=true" /> -->
|
||||
<property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver"></property>
|
||||
<property name="url" value="jdbc:derby://localhost:1527/#{systemProperties['fhir.db.location']};create=true" />
|
||||
<!-- <property name="url" value="jdbc:derby://localhost:1527//opt/glassfish/fhirtest/fhirtest;create=true" /> -->
|
||||
<!--<property name="url" value="jdbc:derby://localhost:1527#{systemProperties['fhir.db.location']};create=true" />-->
|
||||
<property name="username" value="SA"/>
|
||||
<property name="password" value="SA"/>
|
||||
</bean>
|
||||
|
||||
<bean depends-on="dbServer" id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<property name="dataSource" ref="myPersistenceDataSourceDstu1" />
|
||||
<!--
|
||||
<property name="persistenceXmlLocation" value="classpath:META-INF/fhirtest_persistence.xml" />
|
||||
-->
|
||||
<property name="packagesToScan">
|
||||
<list>
|
||||
<value>ca.uhn.fhir.jpa.entity</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="persistenceUnitName" value="FHIR_DSTU2" />
|
||||
<property name="jpaVendorAdapter">
|
||||
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
|
||||
<property name="showSql" value="false" />
|
||||
<property name="generateDdl" value="true" />
|
||||
<property name="databasePlatform" value="org.hibernate.dialect.DerbyTenSevenDialect" />
|
||||
</bean>
|
||||
</property>
|
||||
<property name="jpaPropertyMap">
|
||||
<map>
|
||||
<entry key="hibernate.dialect" value="ca.uhn.fhir.jpa.util.HapiDerbyTenSevenDialect" />
|
||||
<entry key="hibernate.hbm2ddl.auto" value="update" />
|
||||
<entry key="hibernate.jdbc.batch_size" value="20" />
|
||||
<entry key="hibernate.cache.use_minimal_puts" value="true" />
|
||||
<entry key="hibernate.show_sql" value="false" />
|
||||
<entry key="hibernate.cache.use_query_cache" value="false" />
|
||||
<entry key="hibernate.cache.use_second_level_cache" value="false" />
|
||||
<entry key="hibernate.cache.use_structured_entries" value="false" />
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!--for mysql-->
|
||||
<!--
|
||||
<bean depends-on="dbServer" id="myPersistenceDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
|
||||
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
|
||||
<property name="url" value="jdbc:mysql://fhirdb.url/fhirdbname" />
|
||||
<property name="username" value="sa"/>
|
||||
<property name="password" value="sa"/>
|
||||
<property name="testOnBorrow" value="true"/>
|
||||
<property name="validationQuery" value="select 1;"/>
|
||||
</bean>
|
||||
-->
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
|
||||
<property name="entityManagerFactory" ref="entityManagerFactory" />
|
||||
</bean>
|
||||
<tx:annotation-driven transaction-manager="transactionManager" />
|
||||
|
||||
</beans>
|
|
@ -1,69 +0,0 @@
|
|||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:security="http://www.springframework.org/schema/security"
|
||||
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
|
||||
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
|
||||
|
||||
<context:annotation-config />
|
||||
<context:mbean-server />
|
||||
|
||||
<bean depends-on="dbServer" id="myPersistenceDataSourceDstu2" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
|
||||
<property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver"></property>
|
||||
<property name="url" value="jdbc:derby://localhost:1527/#{systemProperties['fhir.db.location.dstu2']};create=true" />
|
||||
<property name="username" value="SA" />
|
||||
<property name="password" value="SA" />
|
||||
</bean>
|
||||
|
||||
<!--for mysql -->
|
||||
<!-- <bean depends-on="dbServer" id="myPersistenceDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"> <property name="driverClassName"
|
||||
value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://fhirdb.url/fhirdbname" /> <property name="username" value="sa"/> <property name="password"
|
||||
value="sa"/> <property name="testOnBorrow" value="true"/> <property name="validationQuery" value="select 1;"/> </bean> -->
|
||||
|
||||
<bean depends-on="dbServer" id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<property name="dataSource" ref="myPersistenceDataSourceDstu2" />
|
||||
<!--
|
||||
<property name="persistenceXmlLocation" value="classpath:META-INF/fhirtest_persistence.xml" />
|
||||
-->
|
||||
<property name="persistenceUnitName" value="FHIR_DSTU2" />
|
||||
<property name="packagesToScan">
|
||||
<list>
|
||||
<value>ca.uhn.fhir.jpa.entity</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="jpaVendorAdapter">
|
||||
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
|
||||
<property name="showSql" value="false" />
|
||||
<property name="generateDdl" value="true" />
|
||||
<property name="databasePlatform" value="org.hibernate.dialect.DerbyTenSevenDialect" />
|
||||
<!-- <property name="databasePlatform" value="ca.uhn.fhir.jpa.util.HapiDerbyTenSevenDialect" />-->
|
||||
<!-- <property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect" /> -->
|
||||
<!-- <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" /> -->
|
||||
</bean>
|
||||
</property>
|
||||
<property name="jpaPropertyMap">
|
||||
<map>
|
||||
<entry key="hibernate.dialect" value="ca.uhn.fhir.jpa.util.HapiDerbyTenSevenDialect" />
|
||||
<entry key="hibernate.hbm2ddl.auto" value="update" />
|
||||
<entry key="hibernate.jdbc.batch_size" value="20" />
|
||||
<entry key="hibernate.cache.use_minimal_puts" value="true" />
|
||||
<entry key="hibernate.show_sql" value="false" />
|
||||
<entry key="hibernate.cache.use_query_cache" value="false" />
|
||||
<entry key="hibernate.cache.use_second_level_cache" value="false" />
|
||||
<entry key="hibernate.cache.use_structured_entries" value="false" />
|
||||
<entry key="hibernate.search.default.directory_provider" value="filesystem" />
|
||||
<entry key="hibernate.search.default.indexBase" value="#{systemProperties['fhir.lucene.location.dstu2']}" />
|
||||
<entry key="hibernate.search.lucene_version" value="LUCENE_CURRENT" />
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
|
||||
<property name="entityManagerFactory" ref="entityManagerFactory" />
|
||||
</bean>
|
||||
<tx:annotation-driven transaction-manager="transactionManager" />
|
||||
|
||||
</beans>
|
|
@ -2,7 +2,7 @@ package ca.uhn.fhir.rest.server;
|
|||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</button>
|
||||
<a class="navbar-brand"
|
||||
th:href="'home?encoding=' + ${encoding} + '&pretty=' + ${pretty}">
|
||||
<i class="fa fa-home topbarIcon" /> HAPI FHIR
|
||||
<i class="fa fa-home topbarIcon" /> Home
|
||||
</a>
|
||||
<a class="navbar-left navbarBreadcrumb hidden-xs hidden-sm"
|
||||
th:if="${resourceName} != null and ${resourceName.empty} == false"
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<li>Jetty (JPA, CLI, Public Server): 9.2.6.v20141205 -> 9.3.4.v20151007 </li>
|
||||
</ul>
|
||||
]]>
|
||||
</action>
|
||||
</action>
|
||||
<action type="add">
|
||||
JPA and Tester Overlay now use Spring Java config files instead
|
||||
of the older XML config files. All example projects have been updated.
|
||||
|
@ -183,6 +183,11 @@
|
|||
Fix a crash when encoding a Binary resource in JSON encoding
|
||||
if the resource has no content-type
|
||||
</action>
|
||||
<action type="fix">
|
||||
JPA server now supports read/history/search in transaction entries
|
||||
by calling the actual implementing method in the server (previously
|
||||
the call was simulated, which meant that many features did not work)
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.2" date="2015-09-18">
|
||||
<action type="add">
|
||||
|
|
Loading…
Reference in New Issue