Allow bundle as param in transaction method
This commit is contained in:
parent
8078452f78
commit
fd41bafa82
|
@ -34,7 +34,7 @@ public class ServerMetadataExamples {
|
|||
String linkAlternate = "Patient/7736";
|
||||
ResourceMetadataKeyEnum.LINK_ALTERNATE.put(patient, linkAlternate);
|
||||
String linkSearch = "Patient?name=smith&name=john";
|
||||
ResourceMetadataKeyEnum.LINK_ALTERNATE.put(patient, linkSearch);
|
||||
ResourceMetadataKeyEnum.LINK_SEARCH.put(patient, linkSearch);
|
||||
|
||||
// Set the published and updated dates
|
||||
InstantDt pubDate = new InstantDt("2011-02-22");
|
||||
|
|
|
@ -83,6 +83,10 @@
|
|||
<action type="fix">
|
||||
Category header (for tags) is correctly read in client for "read" operation
|
||||
</action>
|
||||
<action type="add">
|
||||
Transaction method in server can now have parameter type Bundle instead of
|
||||
List<IResource>
|
||||
</action>
|
||||
</release>
|
||||
<release version="0.5" date="2014-Jul-30">
|
||||
<action type="add">
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.model.view;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core 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.util.List;
|
||||
|
||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||
|
|
|
@ -24,7 +24,15 @@ import java.lang.annotation.ElementType;
|
|||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
|
||||
/**
|
||||
* Parameter annotation for the "transaction" operation. The parameter annotated with this
|
||||
* annotation must be either of type <code>{@link Bundle}</code> or of type
|
||||
* <code>{@link List}<IResource></code>
|
||||
*/
|
||||
@Target(value=ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface TransactionParam {
|
||||
|
|
|
@ -52,9 +52,9 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
|||
|
||||
public TransactionMethodBinding(Method theMethod, FhirContext theConetxt, Object theProvider) {
|
||||
super(null, theMethod, theConetxt, theProvider);
|
||||
|
||||
|
||||
myTransactionParamIndex = -1;
|
||||
int index=0;
|
||||
int index = 0;
|
||||
for (IParameter next : getParameters()) {
|
||||
if (next instanceof TransactionParamBinder) {
|
||||
myTransactionParamIndex = index;
|
||||
|
@ -62,7 +62,7 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
|||
index++;
|
||||
}
|
||||
|
||||
if (myTransactionParamIndex==-1) {
|
||||
if (myTransactionParamIndex == -1) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " does not have a parameter annotated with the @" + TransactionParam.class + " annotation");
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,6 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
|||
return RestfulOperationSystemEnum.TRANSACTION;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean incomingServerRequestMatchesMethod(Request theRequest) {
|
||||
if (theRequest.getRequestType() != RequestType.POST) {
|
||||
|
@ -95,16 +94,23 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
|||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public IBundleProvider invokeServer(Request theRequest, Object[] theMethodParams) throws InvalidRequestException, InternalErrorException {
|
||||
List<IResource> resources = (List<IResource>) theMethodParams[myTransactionParamIndex];
|
||||
|
||||
List<IdDt> oldIds= new ArrayList<IdDt>();
|
||||
|
||||
// Grab the IDs of all of the resources in the transaction
|
||||
List<IResource> resources;
|
||||
if (theMethodParams[myTransactionParamIndex] instanceof Bundle) {
|
||||
resources = ((Bundle) theMethodParams[myTransactionParamIndex]).toListOfResources();
|
||||
} else {
|
||||
resources = (List<IResource>) theMethodParams[myTransactionParamIndex];
|
||||
}
|
||||
List<IdDt> oldIds = new ArrayList<IdDt>();
|
||||
for (IResource next : resources) {
|
||||
oldIds.add(next.getId());
|
||||
}
|
||||
|
||||
Object response= invokeServerMethod(theMethodParams);
|
||||
|
||||
// Call the server implementation method
|
||||
Object response = invokeServerMethod(theMethodParams);
|
||||
IBundleProvider retVal = toResourceList(response);
|
||||
|
||||
|
||||
int offset = 0;
|
||||
if (retVal.size() != resources.size()) {
|
||||
if (retVal.size() > 0 && retVal.getResources(0, 1).get(0) instanceof OperationOutcome) {
|
||||
|
@ -113,22 +119,22 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
|||
throw new InternalErrorException("Transaction bundle contained " + resources.size() + " entries, but server method response contained " + retVal.size() + " entries (must be the same)");
|
||||
}
|
||||
}
|
||||
|
||||
List<IResource> retResources = retVal.getResources(offset, retVal.size());
|
||||
for (int i =0; i < resources.size(); i++) {
|
||||
|
||||
List<IResource> retResources = retVal.getResources(offset, retVal.size());
|
||||
for (int i = 0; i < resources.size(); i++) {
|
||||
IdDt oldId = oldIds.get(i);
|
||||
IResource newRes = retResources.get(i);
|
||||
if (newRes.getId() == null || newRes.getId().isEmpty()) {
|
||||
throw new InternalErrorException("Transaction method returned resource at index " + i + " with no id specified - IResource#setId(IdDt)");
|
||||
}
|
||||
|
||||
|
||||
if (oldId != null && !oldId.isEmpty()) {
|
||||
if (!oldId.equals(newRes.getId())) {
|
||||
newRes.getResourceMetadata().put(ResourceMetadataKeyEnum.PREVIOUS_ID, oldId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -147,11 +153,15 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
|||
|
||||
@Override
|
||||
public BaseHttpClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<IResource> resources = (List<IResource>) theArgs[myTransactionParamIndex];
|
||||
FhirContext context = getContext();
|
||||
|
||||
return createTransactionInvocation(resources, context);
|
||||
if (theArgs[myTransactionParamIndex] instanceof Bundle) {
|
||||
Bundle bundle = (Bundle) theArgs[myTransactionParamIndex];
|
||||
return createTransactionInvocation(bundle, context);
|
||||
} else {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<IResource> resources = (List<IResource>) theArgs[myTransactionParamIndex];
|
||||
return createTransactionInvocation(resources, context);
|
||||
}
|
||||
}
|
||||
|
||||
public static BaseHttpClientInvocation createTransactionInvocation(List<IResource> theResources, FhirContext theContext) {
|
||||
|
|
|
@ -38,40 +38,56 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|||
|
||||
class TransactionParamBinder implements IParameter {
|
||||
|
||||
private boolean myParamIsBundle;
|
||||
|
||||
public TransactionParamBinder() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map<String, List<String>> theTargetQueryArguments, BaseHttpClientInvocation theClientInvocation) throws InternalErrorException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
Bundle resource = (Bundle) theRequestContents;
|
||||
|
||||
if (myParamIsBundle) {
|
||||
return resource;
|
||||
}
|
||||
|
||||
ArrayList<IResource> retVal = new ArrayList<IResource>();
|
||||
for (BundleEntry next : resource.getEntries()) {
|
||||
if (next.getResource() != null) {
|
||||
retVal.add(next.getResource());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@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");
|
||||
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()+">");
|
||||
if (theParameterType.equals(Bundle.class)) {
|
||||
myParamIsBundle=true;
|
||||
if (theInnerCollectionType!=null) {
|
||||
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()
|
||||
+ "> or Bundle");
|
||||
}
|
||||
} else {
|
||||
myParamIsBundle=false;
|
||||
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()
|
||||
+ "> or Bundle");
|
||||
}
|
||||
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()
|
||||
+ "> or Bundle");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core 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 ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.util;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core 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%
|
||||
*/
|
||||
|
||||
public class UrlUtil {
|
||||
|
||||
public static boolean isAbsolute(String theValue) {
|
||||
|
|
|
@ -1201,6 +1201,11 @@
|
|||
<param name="file" value="examples/src/main/java/example/RestfulPatientResourceProviderMore.java" />
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Transaction methods require one parameter annotated with @TransactionParam, and that
|
||||
parameter may be of type List<IResource> or Bundle.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method:
|
||||
<br />
|
||||
|
|
|
@ -75,7 +75,7 @@ public class TransactionClientTest {
|
|||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(createBundle()), Charset.forName("UTF-8")));
|
||||
|
||||
client.searchWithParam(resources);
|
||||
client.transaction(resources);
|
||||
|
||||
assertEquals(HttpPost.class, capt.getValue().getClass());
|
||||
HttpPost post = (HttpPost) capt.getValue();
|
||||
|
@ -92,6 +92,47 @@ public class TransactionClientTest {
|
|||
assertTrue(bundle.getEntries().get(1).getId().isEmpty());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSimpleTransactionWithBundleParam() throws Exception {
|
||||
Patient patient = new Patient();
|
||||
patient.setId(new IdDt("Patient/testPersistWithSimpleLinkP01"));
|
||||
patient.addIdentifier("urn:system", "testPersistWithSimpleLinkP01");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getName().addCoding().setSystem("urn:system").setCode("testPersistWithSimpleLinkO01");
|
||||
obs.setSubject(new ResourceReferenceDt("Patient/testPersistWithSimpleLinkP01"));
|
||||
|
||||
Bundle transactionBundle = Bundle.withResources(Arrays.asList((IResource)patient, obs), ctx, "http://foo");
|
||||
|
||||
IBundleClient client = ctx.newRestfulClient(IBundleClient.class, "http://foo");
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_ATOM_XML + "; charset=UTF-8"));
|
||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(createBundle()), Charset.forName("UTF-8")));
|
||||
|
||||
client.transaction(transactionBundle);
|
||||
|
||||
assertEquals(HttpPost.class, capt.getValue().getClass());
|
||||
HttpPost post = (HttpPost) capt.getValue();
|
||||
assertEquals("http://foo/", post.getURI().toString());
|
||||
|
||||
Bundle bundle = ctx.newXmlParser().parseBundle(new InputStreamReader(post.getEntity().getContent()));
|
||||
ourLog.info(ctx.newXmlParser().setPrettyPrint(true).encodeBundleToString(bundle));
|
||||
|
||||
assertEquals(2, bundle.size());
|
||||
assertEquals("http://foo/Patient/testPersistWithSimpleLinkP01", bundle.getEntries().get(0).getId().getValue());
|
||||
assertEquals("http://foo/Patient/testPersistWithSimpleLinkP01", bundle.getEntries().get(0).getLinkSelf().getValue());
|
||||
assertEquals(null, bundle.getEntries().get(0).getLinkAlternate().getValue());
|
||||
|
||||
assertTrue(bundle.getEntries().get(1).getId().isEmpty());
|
||||
|
||||
}
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TransactionClientTest.class);
|
||||
private String createBundle() {
|
||||
return ctx.newXmlParser().encodeBundleToString(new Bundle());
|
||||
|
@ -100,7 +141,15 @@ public class TransactionClientTest {
|
|||
private interface IClient extends IBasicClient {
|
||||
|
||||
@Transaction
|
||||
public List<IResource> searchWithParam(@TransactionParam List<IResource> theResources);
|
||||
public List<IResource> transaction(@TransactionParam List<IResource> theResources);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private interface IBundleClient extends IBasicClient {
|
||||
|
||||
@Transaction
|
||||
public List<IResource> transaction(@TransactionParam Bundle theResources);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -232,7 +232,7 @@ public class SearchTest {
|
|||
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||
|
||||
@Search
|
||||
public List<Patient> findPatient(@OptionalParam(name = "_id") StringParam theParam) {
|
||||
public List<Patient> findPatient(@RequiredParam(name = "_id") StringParam theParam) {
|
||||
ArrayList<Patient> retVal = new ArrayList<Patient>();
|
||||
|
||||
Patient patient = new Patient();
|
||||
|
@ -246,7 +246,7 @@ public class SearchTest {
|
|||
}
|
||||
|
||||
@Search
|
||||
public List<Patient> findPatientByAAA01(@OptionalParam(name = "AAA") StringParam theParam) {
|
||||
public List<Patient> findPatientByAAA01(@RequiredParam(name = "AAA") StringParam theParam) {
|
||||
ArrayList<Patient> retVal = new ArrayList<Patient>();
|
||||
|
||||
Patient patient = new Patient();
|
||||
|
|
|
@ -0,0 +1,234 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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.ServletHolder;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
||||
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 TransactionWithBundleParamTest {
|
||||
|
||||
private static CloseableHttpClient ourClient;
|
||||
private static FhirContext ourCtx = new FhirContext();
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TransactionWithBundleParamTest.class);
|
||||
private static int ourPort;
|
||||
private static boolean ourReturnOperationOutcome;
|
||||
|
||||
private static Server ourServer;
|
||||
|
||||
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
ourReturnOperationOutcome = false;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransaction() throws Exception {
|
||||
Bundle b = new Bundle();
|
||||
InstantDt nowInstant = InstantDt.withCurrentTime();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.addName().addFamily("Family1");
|
||||
BundleEntry entry = b.addEntry();
|
||||
entry.getId().setValue("1");
|
||||
entry.setResource(p1);
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.addName().addFamily("Family2");
|
||||
entry = b.addEntry();
|
||||
entry.getId().setValue("2");
|
||||
entry.setResource(p2);
|
||||
|
||||
BundleEntry deletedEntry = b.addEntry();
|
||||
deletedEntry.setId(new IdDt("Patient/3"));
|
||||
deletedEntry.setDeleted(nowInstant);
|
||||
|
||||
String bundleString = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
|
||||
ourLog.info(bundleString);
|
||||
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/");
|
||||
httpPost.addHeader("Accept", Constants.CT_ATOM_XML + "; pretty=true");
|
||||
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()); IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
|
||||
ourLog.info(responseContent);
|
||||
|
||||
Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
|
||||
assertEquals(3, bundle.size());
|
||||
|
||||
BundleEntry entry0 = bundle.getEntries().get(0);
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/81", entry0.getId().getValue());
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/81/_history/91", entry0.getLinkSelf().getValue());
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/1", entry0.getLinkAlternate().getValue());
|
||||
|
||||
BundleEntry entry1 = bundle.getEntries().get(1);
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/82", entry1.getId().getValue());
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/82/_history/92", entry1.getLinkSelf().getValue());
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/2", entry1.getLinkAlternate().getValue());
|
||||
|
||||
BundleEntry entry2 = bundle.getEntries().get(2);
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/3", entry2.getId().getValue());
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/3/_history/93", entry2.getLinkSelf().getValue());
|
||||
assertEquals(nowInstant.getValueAsString(), entry2.getDeletedAt().getValueAsString());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionWithOperationOutcome() throws Exception {
|
||||
ourReturnOperationOutcome = true;
|
||||
|
||||
Bundle b = new Bundle();
|
||||
InstantDt nowInstant = InstantDt.withCurrentTime();
|
||||
|
||||
Patient p1 = new Patient();
|
||||
p1.addName().addFamily("Family1");
|
||||
BundleEntry entry = b.addEntry();
|
||||
entry.getId().setValue("1");
|
||||
entry.setResource(p1);
|
||||
|
||||
Patient p2 = new Patient();
|
||||
p2.addName().addFamily("Family2");
|
||||
entry = b.addEntry();
|
||||
entry.getId().setValue("2");
|
||||
entry.setResource(p2);
|
||||
|
||||
BundleEntry deletedEntry = b.addEntry();
|
||||
deletedEntry.setId(new IdDt("Patient/3"));
|
||||
deletedEntry.setDeleted(nowInstant);
|
||||
|
||||
String bundleString = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b);
|
||||
ourLog.info(bundleString);
|
||||
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/");
|
||||
httpPost.addHeader("Accept", Constants.CT_ATOM_XML + "; pretty=true");
|
||||
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()); IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
|
||||
ourLog.info(responseContent);
|
||||
|
||||
Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
|
||||
assertEquals(4, bundle.size());
|
||||
|
||||
assertEquals(OperationOutcome.class, bundle.getEntries().get(0).getResource().getClass());
|
||||
assertEquals("OperationOutcome (no ID)", bundle.getEntries().get(0).getTitle().getValue());
|
||||
|
||||
BundleEntry entry0 = bundle.getEntries().get(1);
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/81", entry0.getId().getValue());
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/81/_history/91", entry0.getLinkSelf().getValue());
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/1", entry0.getLinkAlternate().getValue());
|
||||
|
||||
BundleEntry entry1 = bundle.getEntries().get(2);
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/82", entry1.getId().getValue());
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/82/_history/92", entry1.getLinkSelf().getValue());
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/2", entry1.getLinkAlternate().getValue());
|
||||
|
||||
BundleEntry entry2 = bundle.getEntries().get(3);
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/3", entry2.getId().getValue());
|
||||
assertEquals("http://localhost:" + ourPort + "/Patient/3/_history/93", entry2.getLinkSelf().getValue());
|
||||
assertEquals(nowInstant.getValueAsString(), entry2.getDeletedAt().getValueAsString());
|
||||
}
|
||||
|
||||
@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();
|
||||
RestfulServer server = new RestfulServer();
|
||||
server.setProviders(patientProvider);
|
||||
|
||||
org.eclipse.jetty.servlet.ServletContextHandler proxyHandler = new org.eclipse.jetty.servlet.ServletContextHandler();
|
||||
proxyHandler.setContextPath("/");
|
||||
|
||||
ServletHolder handler = new ServletHolder();
|
||||
handler.setServlet(server);
|
||||
proxyHandler.addServlet(handler, "/*");
|
||||
|
||||
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 Bundle theResources) {
|
||||
int index=1;
|
||||
for (IResource next : theResources.toListOfResources()) {
|
||||
String newId = "8"+Integer.toString(index);
|
||||
if (next.getResourceMetadata().containsKey(ResourceMetadataKeyEnum.DELETED_AT)) {
|
||||
newId = next.getId().getIdPart();
|
||||
}
|
||||
next.setId(new IdDt("Patient", newId, "9"+Integer.toString(index)));
|
||||
index++;
|
||||
}
|
||||
|
||||
List<IResource> retVal = theResources.toListOfResources();
|
||||
if (ourReturnOperationOutcome) {
|
||||
retVal = new ArrayList<IResource>();
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
oo.addIssue().setDetails("AAAAA");
|
||||
retVal.add(oo);
|
||||
retVal.addAll(theResources.toListOfResources());
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue