Work on support for transaction searches with paging in JPA

This commit is contained in:
James Agnew 2015-10-19 20:21:06 -04:00
parent 39fce055e1
commit 6729ea0479
12 changed files with 201 additions and 109 deletions

View File

@ -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)) {

View File

@ -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
}
}

View File

@ -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

View File

@ -22,9 +22,11 @@ package ca.uhn.fhir.jpa.dao;
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 static org.hamcrest.Matchers.emptyCollectionOf;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@ -35,6 +37,7 @@ import javax.persistence.TypedQuery;
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;
@ -44,6 +47,7 @@ import org.springframework.transaction.support.TransactionTemplate;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.entity.TagDefinition;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
@ -59,8 +63,11 @@ import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.method.MethodUtil;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
@ -83,12 +90,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);
@ -109,7 +116,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;
}
};
@ -173,19 +180,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) {
@ -324,6 +331,9 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
}
if (parts.getResourceId() != null && parts.getParams() == null) {
/*
* GET is a read
*/
IResource found;
boolean notChanged = false;
if (parts.getVersionId() != null) {
@ -350,24 +360,26 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle> {
resp.setStatus(toStatusString(Constants.STATUS_HTTP_304_NOT_MODIFIED));
}
} else if (parts.getParams() != null) {
/*
* GET is a search
*/
RuntimeResourceDefinition def = getContext().getResourceDefinition(dao.getResourceType());
SearchParameterMap params = translateMatchUrl(url, def);
IBundleProvider bundle = dao.search(params);
Bundle searchBundle = new Bundle();
searchBundle.setTotal(bundle.size());
Integer count = params.getCount();
if (count == null) {
count = bundle.preferredPageSize();
}
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);
}
IVersionSpecificBundleFactory bundleFactory = getContext().newBundleFactory();
Set<Include> includes = new HashSet<Include>();
EncodingEnum linkEncoding = null;
bundleFactory.initializeBundleFromBundleProvider(theRequestDetails.getServer(), bundle, linkEncoding, theRequestDetails.getFhirServerBase(), url, false, 0, count, null, ca.uhn.fhir.model.valueset.BundleTypeEnum.SEARCHSET, includes);
Entry newEntry = response.addEntry();
newEntry.setResource(searchBundle);
newEntry.setResource((IResource) bundleFactory.getResourceBundle());
newEntry.getResponse().setStatus(toStatusString(Constants.STATUS_HTTP_200_OK));
}
}

View File

@ -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);
}

View File

@ -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) {
@ -55,7 +66,7 @@ public class BaseJpaProvider {
}
b.append(enums.nextElement());
}
String forwardedFor = b.toString();
String ip = theRequest.getRemoteAddr();
if (StringUtils.isBlank(forwardedFor)) {
@ -68,12 +79,11 @@ public class BaseJpaProvider {
String userAgent = StringUtils.defaultString(theRequest.getHeader("user-agent"));
org.slf4j.MDC.put(REMOTE_UA, userAgent);
}
public void endRequest(HttpServletRequest theRequest) {
MDC.remove(REMOTE_ADDR);
MDC.remove(REMOTE_UA);
public void startRequest(RequestDetails theRequest) {
startRequest(theRequest.getServletRequest());
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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());
@ -182,6 +185,11 @@ public class FhirSystemDaoDstu1Test extends BaseJpaTest {
assertEquals(obsVersion2, "2");
}
@Before
public void before() {
myRequestDetails = mock(RequestDetails.class);
}
@Test
public void testPersistWithUnknownId() {
@ -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

View File

@ -14,8 +14,10 @@ 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;
@ -23,15 +25,14 @@ import java.util.ArrayList;
import java.util.List;
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;
@ -47,7 +48,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 +58,12 @@ 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.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,14 +73,25 @@ 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;
@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() {
@ -262,7 +274,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 +302,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 +310,12 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
}
@Before
public void before() {
myRequestDetails = mock(RequestDetails.class);
when(myRequestDetails.getServer()).thenReturn(new RestfulServer());
}
@Test
public void testTransactionSingleEmptyResource() {
@ -307,7 +325,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 +345,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 +395,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 +415,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 +423,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 +431,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 +453,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 +488,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 +511,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 +543,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 +582,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 +601,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 +631,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 +665,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 +719,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 +734,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 +754,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 +781,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 +791,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 +810,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 +835,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 +857,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 +893,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 +961,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 +975,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 +984,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 +1010,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());
@ -1036,7 +1054,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 +1101,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 +1128,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 +1168,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 +1311,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 +1354,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 +1373,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();
}
}

View File

@ -20,9 +20,11 @@ import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.junit.AfterClass;
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.TestDstu2Config;
import ca.uhn.fhir.jpa.dao.BaseJpaTest;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.rp.dstu2.ObservationResourceProvider;
@ -49,7 +51,7 @@ public class SystemProviderDstu2Test extends BaseJpaTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SystemProviderDstu2Test.class);
private static Server ourServer;
private static ClassPathXmlApplicationContext ourAppCtx;
private static AnnotationConfigApplicationContext ourAppCtx;
private static FhirContext ourCtx;
private static IGenericClient ourClient;
private static String ourServerBase;
@ -210,7 +212,7 @@ public class SystemProviderDstu2Test extends BaseJpaTest {
@SuppressWarnings("unchecked")
@BeforeClass
public static void beforeClass() throws Exception {
ourAppCtx = new ClassPathXmlApplicationContext("fhir-jpabase-spring-test-config.xml", "hapi-fhir-server-resourceproviders-dstu2.xml");
ourAppCtx = new AnnotationConfigApplicationContext(TestDstu2Config.class);
IFhirResourceDao<Patient> patientDao = (IFhirResourceDao<Patient>) ourAppCtx.getBean("myPatientDaoDstu2", IFhirResourceDao.class);
PatientResourceProvider patientRp = new PatientResourceProvider();