More work on transaction method
This commit is contained in:
parent
62b909ff22
commit
30065fdfae
|
@ -0,0 +1,41 @@
|
|||
package ca.uhn.fhir.rest.annotation;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR Library
|
||||
* %%
|
||||
* Copyright (C) 2014 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.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
|
||||
/**
|
||||
* RESTful method annotation to be used for the FHIR <a href="http://hl7.org/implement/standards/fhir/http.html#transaction">transaction</a> method.
|
||||
*
|
||||
* <p>
|
||||
* This method should have a parameter of type {@link Bundle} annotated with the {@link TransactionParam} annotation.
|
||||
* </p>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Transaction {
|
||||
// nothing
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package ca.uhn.fhir.rest.annotation;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR Library
|
||||
* %%
|
||||
* Copyright (C) 2014 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.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(value=ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface TransactionParam {
|
||||
|
||||
}
|
|
@ -56,6 +56,7 @@ import ca.uhn.fhir.rest.annotation.History;
|
|||
import ca.uhn.fhir.rest.annotation.Metadata;
|
||||
import ca.uhn.fhir.rest.annotation.Read;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.annotation.Transaction;
|
||||
import ca.uhn.fhir.rest.annotation.Update;
|
||||
import ca.uhn.fhir.rest.annotation.Validate;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
|
@ -172,8 +173,9 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
GetTags getTags = theMethod.getAnnotation(GetTags.class);
|
||||
AddTags addTags = theMethod.getAnnotation(AddTags.class);
|
||||
DeleteTags deleteTags = theMethod.getAnnotation(DeleteTags.class);
|
||||
Transaction transaction = theMethod.getAnnotation(Transaction.class);
|
||||
// ** if you add another annotation above, also add it to the next line:
|
||||
if (!verifyMethodHasZeroOrOneOperationAnnotation(theMethod, read, search, conformance, create, update, delete, history, validate, getTags, addTags, deleteTags)) {
|
||||
if (!verifyMethodHasZeroOrOneOperationAnnotation(theMethod, read, search, conformance, create, update, delete, history, validate, getTags, addTags, deleteTags,transaction)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -283,6 +285,8 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
|
|||
return new AddTagsMethodBinding(theMethod, theContext, theProvider, addTags);
|
||||
} else if (deleteTags != null) {
|
||||
return new DeleteTagsMethodBinding(theMethod, theContext, theProvider, deleteTags);
|
||||
} else if (transaction != null) {
|
||||
return new TransactionMethodBinding(theMethod, theContext, theProvider);
|
||||
} else {
|
||||
throw new ConfigurationException("Did not detect any FHIR annotations on method '" + theMethod.getName() + "' on type: " + theMethod.getDeclaringClass().getCanonicalName());
|
||||
}
|
||||
|
|
|
@ -209,13 +209,15 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
if (uaHeader != null && uaHeader.contains("Mozilla")) {
|
||||
requestIsBrowser = true;
|
||||
}
|
||||
|
||||
Object requestObject = parseRequestObject(theRequest);
|
||||
|
||||
// Method params
|
||||
Object[] params = new Object[getParameters().size()];
|
||||
for (int i = 0; i < getParameters().size(); i++) {
|
||||
IParameter param = getParameters().get(i);
|
||||
if (param != null) {
|
||||
params[i] = param.translateQueryParametersIntoServerArgument(theRequest, null);
|
||||
params[i] = param.translateQueryParametersIntoServerArgument(theRequest, requestObject);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -235,6 +237,13 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override
|
||||
*/
|
||||
protected Object parseRequestObject(@SuppressWarnings("unused") Request theRequest) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static IdDt getIdFromMetadataOrNullIfNone(Map<ResourceMetadataKeyEnum, Object> theResourceMetadata, ResourceMetadataKeyEnum theKey) {
|
||||
Object retValObj = theResourceMetadata.get(theKey);
|
||||
if (retValObj == null) {
|
||||
|
|
|
@ -1,45 +1,45 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
|
||||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||
import ca.uhn.fhir.rest.client.BaseClientInvocation;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.method.SearchMethodBinding.RequestType;
|
||||
import ca.uhn.fhir.rest.param.TransactionParameter;
|
||||
import ca.uhn.fhir.rest.param.IParameter;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class TransactionMethodBinding extends BaseResourceReturningMethodBinding {
|
||||
|
||||
private int myResourceParameterIndex;
|
||||
|
||||
public TransactionMethodBinding(Method theMethod, FhirContext theConetxt, Object theProvider) {
|
||||
super(null, theMethod, theConetxt, theProvider);
|
||||
}
|
||||
|
||||
myResourceParameterIndex = -1;
|
||||
int index=0;
|
||||
for (IParameter next : getParameters()) {
|
||||
if (next instanceof TransactionParameter) {
|
||||
myResourceParameterIndex = index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResourceName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestfulOperationTypeEnum getResourceOperationType() {
|
||||
return null;
|
||||
if (myResourceParameterIndex==-1) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " does not have a parameter annotated with the @" + TransactionParam.class + " annotation");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -47,22 +47,19 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
|||
return RestfulOperationSystemEnum.TRANSACTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invokeServer(RestfulServer theServer, Request theRequest, HttpServletResponse theResponse) throws BaseServerResponseException, IOException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean incomingServerRequestMatchesMethod(Request theRequest) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
if (theRequest.getRequestType() != RequestType.POST) {
|
||||
return false;
|
||||
}
|
||||
if (isNotBlank(theRequest.getOperation())) {
|
||||
return false;
|
||||
}
|
||||
if (isNotBlank(theRequest.getResourceName())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,6 +69,26 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
|||
|
||||
@Override
|
||||
public List<IResource> invokeServer(Request theRequest, Object[] theMethodParams) throws InvalidRequestException, InternalErrorException {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<IResource> retVal=(List<IResource>) invokeServerMethod(theMethodParams);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object parseRequestObject(Request theRequest) {
|
||||
EncodingEnum encoding = determineResponseEncoding(theRequest);
|
||||
IParser parser = encoding.newParser(getContext());
|
||||
Bundle bundle = parser.parseBundle(theRequest.getInputReader());
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestfulOperationTypeEnum getResourceOperationType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ import ca.uhn.fhir.model.api.annotation.Description;
|
|||
import ca.uhn.fhir.model.api.annotation.TagListParam;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.IntegerDt;
|
||||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||
import ca.uhn.fhir.rest.annotation.Count;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.IncludeParam;
|
||||
|
@ -225,6 +226,8 @@ public class ParameterUtil {
|
|||
param = new CountParameter();
|
||||
} else if (nextAnnotation instanceof Sort) {
|
||||
param = new SortParameter();
|
||||
} else if (nextAnnotation instanceof TransactionParam) {
|
||||
param = new TransactionParameter();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR Library
|
||||
* %%
|
||||
* Copyright (C) 2014 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 ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||
import ca.uhn.fhir.rest.client.BaseClientInvocation;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class TransactionParameter implements IParameter {
|
||||
|
||||
public TransactionParameter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map<String, List<String>> theTargetQueryArguments, BaseClientInvocation theClientInvocation) throws InternalErrorException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
Bundle resource = (Bundle) theRequestContents;
|
||||
return resource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
|
||||
if (theOuterCollectionType != null) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" +theMethod.getDeclaringClass().getCanonicalName()+ "' is annotated with @" + TransactionParam.class.getName() + " but can not be a collection of collections");
|
||||
}
|
||||
if (theInnerCollectionType.equals(List.class)==false) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" +theMethod.getDeclaringClass().getCanonicalName()+ "' is annotated with @" + TransactionParam.class.getName() + " but is not of type List<" + IResource.class.getCanonicalName()+">");
|
||||
}
|
||||
if (theParameterType.equals(IResource.class)==false) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" +theMethod.getDeclaringClass().getCanonicalName()+ "' is annotated with @" + TransactionParam.class.getName() + " but is not of type List<" + IResource.class.getCanonicalName()+">");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -89,12 +89,10 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
|
||||
/**
|
||||
* This method is called prior to sending a response to incoming requests.
|
||||
* It is used to add custom headers.
|
||||
* This method is called prior to sending a response to incoming requests. It is used to add custom headers.
|
||||
* <p>
|
||||
* Use caution if overriding this method: it is recommended to call
|
||||
* <code>super.addHeadersToResponse</code> to avoid inadvertantly disabling
|
||||
* functionality.
|
||||
* Use caution if overriding this method: it is recommended to call <code>super.addHeadersToResponse</code> to avoid
|
||||
* inadvertantly disabling functionality.
|
||||
* </p>
|
||||
*/
|
||||
public void addHeadersToResponse(HttpServletResponse theHttpResponse) {
|
||||
|
@ -102,17 +100,15 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link FhirContext} associated with this server. For efficient
|
||||
* processing, resource providers and plain providers should generally use
|
||||
* this context if one is needed, as opposed to creating their own.
|
||||
* Gets the {@link FhirContext} associated with this server. For efficient processing, resource providers and plain
|
||||
* providers should generally use this context if one is needed, as opposed to creating their own.
|
||||
*/
|
||||
public FhirContext getFhirContext() {
|
||||
return myFhirContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the non-resource specific providers which implement method calls
|
||||
* on this server
|
||||
* Provides the non-resource specific providers which implement method calls on this server
|
||||
*
|
||||
* @see #getResourceProviders()
|
||||
*/
|
||||
|
@ -139,12 +135,11 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the server conformance provider, which is the provider that is
|
||||
* used to generate the server's conformance (metadata) statement.
|
||||
* Returns the server conformance provider, which is the provider that is used to generate the server's conformance
|
||||
* (metadata) statement.
|
||||
* <p>
|
||||
* By default, the {@link ServerConformanceProvider} is used, but this can
|
||||
* be changed, or set to <code>null</code> if you do not wish to export a
|
||||
* conformance statement.
|
||||
* By default, the {@link ServerConformanceProvider} is used, but this can be changed, or set to <code>null</code>
|
||||
* if you do not wish to export a conformance statement.
|
||||
* </p>
|
||||
*/
|
||||
public Object getServerConformanceProvider() {
|
||||
|
@ -152,9 +147,8 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the server's name, as exported in conformance profiles exported by
|
||||
* the server. This is informational only, but can be helpful to set with
|
||||
* something appropriate.
|
||||
* Gets the server's name, as exported in conformance profiles exported by the server. This is informational only,
|
||||
* but can be helpful to set with something appropriate.
|
||||
*
|
||||
* @see RestfulServer#setServerName(StringDt)
|
||||
*/
|
||||
|
@ -167,19 +161,17 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the server's version, as exported in conformance profiles exported
|
||||
* by the server. This is informational only, but can be helpful to set with
|
||||
* something appropriate.
|
||||
* Gets the server's version, as exported in conformance profiles exported by the server. This is informational
|
||||
* only, but can be helpful to set with something appropriate.
|
||||
*/
|
||||
public String getServerVersion() {
|
||||
return myServerVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
@Override
|
||||
public final void init() throws ServletException {
|
||||
|
@ -237,8 +229,7 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the non-resource specific providers which implement method calls on
|
||||
* this server.
|
||||
* Sets the non-resource specific providers which implement method calls on this server.
|
||||
*
|
||||
* @see #setResourceProviders(Collection)
|
||||
*/
|
||||
|
@ -247,8 +238,7 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the non-resource specific providers which implement method calls on
|
||||
* this server.
|
||||
* Sets the non-resource specific providers which implement method calls on this server.
|
||||
*
|
||||
* @see #setResourceProviders(Collection)
|
||||
*/
|
||||
|
@ -257,8 +247,7 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the non-resource specific providers which implement method calls on
|
||||
* this server
|
||||
* Sets the non-resource specific providers which implement method calls on this server
|
||||
*
|
||||
* @see #setResourceProviders(Collection)
|
||||
*/
|
||||
|
@ -288,19 +277,16 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the server conformance provider, which is the provider that is
|
||||
* used to generate the server's conformance (metadata) statement.
|
||||
* Returns the server conformance provider, which is the provider that is used to generate the server's conformance
|
||||
* (metadata) statement.
|
||||
* <p>
|
||||
* By default, the {@link ServerConformanceProvider} is used, but this can
|
||||
* be changed, or set to <code>null</code> if you do not wish to export a
|
||||
* conformance statement.
|
||||
* By default, the {@link ServerConformanceProvider} is used, but this can be changed, or set to <code>null</code>
|
||||
* if you do not wish to export a conformance statement.
|
||||
* </p>
|
||||
* Note that this method can only be called before the server is
|
||||
* initialized.
|
||||
* Note that this method can only be called before the server is initialized.
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* Note that this method can only be called prior to
|
||||
* {@link #init() initialization} and will throw an
|
||||
* Note that this method can only be called prior to {@link #init() initialization} and will throw an
|
||||
* {@link IllegalStateException} if called after that.
|
||||
*/
|
||||
public void setServerConformanceProvider(Object theServerConformanceProvider) {
|
||||
|
@ -311,9 +297,8 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the server's name, as exported in conformance profiles exported by
|
||||
* the server. This is informational only, but can be helpful to set with
|
||||
* something appropriate.
|
||||
* Gets the server's name, as exported in conformance profiles exported by the server. This is informational only,
|
||||
* but can be helpful to set with something appropriate.
|
||||
*
|
||||
* @see RestfulServer#setServerName(StringDt)
|
||||
*/
|
||||
|
@ -322,18 +307,16 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the server's version, as exported in conformance profiles exported
|
||||
* by the server. This is informational only, but can be helpful to set with
|
||||
* something appropriate.
|
||||
* Gets the server's version, as exported in conformance profiles exported by the server. This is informational
|
||||
* only, but can be helpful to set with something appropriate.
|
||||
*/
|
||||
public void setServerVersion(String theServerVersion) {
|
||||
myServerVersion = theServerVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to <code>true</code> (default is false), the server will use
|
||||
* browser friendly content-types (instead of standard FHIR ones) when it
|
||||
* detects that the request is coming from a browser instead of a FHIR
|
||||
* If set to <code>true</code> (default is false), the server will use browser friendly content-types (instead of
|
||||
* standard FHIR ones) when it detects that the request is coming from a browser instead of a FHIR
|
||||
*/
|
||||
public void setUseBrowserFriendlyContentTypes(boolean theUseBrowserFriendlyContentTypes) {
|
||||
myUseBrowserFriendlyContentTypes = theUseBrowserFriendlyContentTypes;
|
||||
|
@ -361,7 +344,7 @@ public class RestfulServer extends HttpServlet {
|
|||
private void findResourceMethods(Object theProvider, Class<?> clazz) {
|
||||
for (Method m : clazz.getDeclaredMethods()) {
|
||||
if (!Modifier.isPublic(m.getModifiers())) {
|
||||
ourLog.debug("Ignoring non-public method: {}",m);
|
||||
ourLog.debug("Ignoring non-public method: {}", m);
|
||||
} else {
|
||||
if (!Modifier.isStatic(m.getModifiers())) {
|
||||
ourLog.debug("Scanning public method: {}#{}", theProvider.getClass(), m.getName());
|
||||
|
@ -521,13 +504,12 @@ public class RestfulServer extends HttpServlet {
|
|||
Map<String, String[]> params = new HashMap<String, String[]>(theRequest.getParameterMap());
|
||||
|
||||
StringTokenizer tok = new StringTokenizer(requestPath, "/");
|
||||
if (!tok.hasMoreTokens()) {
|
||||
throw new ResourceNotFoundException("No resource name specified");
|
||||
}
|
||||
resourceName = tok.nextToken();
|
||||
if (resourceName.startsWith("_")) {
|
||||
operation = resourceName;
|
||||
resourceName = null;
|
||||
if (tok.hasMoreTokens()) {
|
||||
resourceName = tok.nextToken();
|
||||
if (resourceName.startsWith("_")) {
|
||||
operation = resourceName;
|
||||
resourceName = null;
|
||||
}
|
||||
}
|
||||
|
||||
ResourceBinding resourceBinding = null;
|
||||
|
@ -570,16 +552,16 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
|
||||
// Secondary is for things like ..../_tags/_delete
|
||||
String secondaryOperation=null;
|
||||
|
||||
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);
|
||||
} else if (secondaryOperation == null) {
|
||||
secondaryOperation = nextString;
|
||||
} else {
|
||||
throw new InvalidRequestException("URL path has unexpected token '" + nextString + "' at the end: " + requestPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -653,8 +635,8 @@ public class RestfulServer extends HttpServlet {
|
|||
}
|
||||
|
||||
/**
|
||||
* This method may be overridden by subclasses to do perform initialization
|
||||
* that needs to be performed prior to the server being used.
|
||||
* This method may be overridden by subclasses to do perform initialization that needs to be performed prior to the
|
||||
* server being used.
|
||||
*/
|
||||
protected void initialize() {
|
||||
// nothing by default
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.rest.annotation.Transaction;
|
||||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||
import ca.uhn.fhir.testutil.RandomServerPortProvider;
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public class TransactionTest {
|
||||
|
||||
private static CloseableHttpClient ourClient;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TransactionTest.class);
|
||||
private static int ourPort;
|
||||
private static Server ourServer;
|
||||
private static FhirContext ourCtx = new FhirContext();
|
||||
|
||||
@Test
|
||||
public void testTransaction() throws Exception {
|
||||
Bundle b= new Bundle();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.getId().setValue("1");
|
||||
b.addEntry().setResource(p1);
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.getId().setValue("2");
|
||||
b.addEntry().setResource(p2);
|
||||
|
||||
BundleEntry deletedEntry = b.addEntry();
|
||||
deletedEntry.setId(new IdDt("3"));
|
||||
deletedEntry.setDeleted(new InstantDt());
|
||||
|
||||
String bundleString = ourCtx.newXmlParser().encodeBundleToString(b);
|
||||
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/");
|
||||
httpPost.setEntity(new StringEntity(bundleString, ContentType.create(Constants.CT_ATOM_XML, "UTF-8")));
|
||||
HttpResponse status = ourClient.execute(httpPost);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
|
||||
assertEquals(3, bundle.size());
|
||||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws Exception {
|
||||
ourServer.stop();
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
ourPort = RandomServerPortProvider.findFreePort();
|
||||
ourServer = new Server(ourPort);
|
||||
|
||||
DummyProvider patientProvider = new DummyProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
RestfulServer servlet = new RestfulServer();
|
||||
servlet.setProviders(patientProvider);
|
||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
ourServer.start();
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
builder.setConnectionManager(connectionManager);
|
||||
ourClient = builder.build();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by dsotnikov on 2/25/2014.
|
||||
*/
|
||||
public static class DummyProvider {
|
||||
|
||||
@Transaction
|
||||
public List<IResource> transaction(@TransactionParam List<IResource> theResources) {
|
||||
return theResources;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue