JPA server interceptor methods for create/update/delete provided the wrong version ID to the interceptors
This commit is contained in:
parent
bcff22c769
commit
0c6679ac44
|
@ -179,7 +179,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
}
|
||||
|
||||
@Override
|
||||
public ResourceTable delete(IIdType theId, List<DeleteConflict> deleteConflicts, RequestDetails theRequestDetails) {
|
||||
public DaoMethodOutcome delete(IIdType theId, List<DeleteConflict> deleteConflicts, RequestDetails theRequestDetails) {
|
||||
if (theId == null || !theId.hasIdPart()) {
|
||||
throw new InvalidRequestException("Can not perform delete, no ID provided");
|
||||
}
|
||||
|
@ -188,6 +188,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
throw new ResourceVersionConflictException("Trying to delete " + theId + " but this is not the current version");
|
||||
}
|
||||
|
||||
StopWatch w = new StopWatch();
|
||||
|
||||
T resourceToDelete = toResource(myResourceType, entity, false);
|
||||
|
||||
validateOkToDelete(deleteConflicts, entity);
|
||||
|
@ -202,6 +204,16 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
Date updateTime = new Date();
|
||||
ResourceTable savedEntity = updateEntity(null, entity, updateTime, updateTime);
|
||||
resourceToDelete.setId(entity.getIdDt());
|
||||
|
||||
// /*
|
||||
// * If we aren't indexing (meaning we're probably executing a sub-operation within a transaction),
|
||||
// * we'll manually increase the version. This is important because we want the updated version number
|
||||
// * to be reflected in the resource shared with interceptors
|
||||
// */
|
||||
// if (!thePerformIndexing) {
|
||||
// incremenetId(resourceToDelete);
|
||||
// }
|
||||
|
||||
// Notify JPA interceptors
|
||||
if (theRequestDetails != null) {
|
||||
|
@ -214,7 +226,16 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
}
|
||||
}
|
||||
|
||||
return savedEntity;
|
||||
DaoMethodOutcome outcome = toMethodOutcome(savedEntity, resourceToDelete).setCreated(true);
|
||||
|
||||
IBaseOperationOutcome oo = OperationOutcomeUtil.newInstance(getContext());
|
||||
String message = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulDeletes", 1, w.getMillis());
|
||||
String severity = "information";
|
||||
String code = "informational";
|
||||
OperationOutcomeUtil.addIssue(getContext(), oo, severity, message, null, code);
|
||||
outcome.setOperationOutcome(oo);
|
||||
|
||||
return outcome;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -222,24 +243,22 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
List<DeleteConflict> deleteConflicts = new ArrayList<DeleteConflict>();
|
||||
StopWatch w = new StopWatch();
|
||||
|
||||
ResourceTable savedEntity = delete(theId, deleteConflicts, theRequestDetails);
|
||||
DaoMethodOutcome retVal = delete(theId, deleteConflicts, theRequestDetails);
|
||||
|
||||
validateDeleteConflictsEmptyOrThrowException(deleteConflicts);
|
||||
|
||||
IBaseOperationOutcome oo = OperationOutcomeUtil.newInstance(getContext());
|
||||
String message = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulDeletes", 1, w.getMillis());
|
||||
String severity = "information";
|
||||
String code = "informational";
|
||||
OperationOutcomeUtil.addIssue(getContext(), oo, severity, message, null, code);
|
||||
|
||||
ourLog.info("Processed delete on {} in {}ms", theId.getValue(), w.getMillisAndRestart());
|
||||
DaoMethodOutcome retVal = toMethodOutcome(savedEntity, null);
|
||||
retVal.setOperationOutcome(oo);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method gets called by {@link #deleteByUrl(String, List, RequestDetails)} as well as by
|
||||
* transaction processors
|
||||
*/
|
||||
@Override
|
||||
public List<ResourceTable> deleteByUrl(String theUrl, List<DeleteConflict> deleteConflicts, RequestDetails theRequestDetails) {
|
||||
public DeleteMethodOutcome deleteByUrl(String theUrl, List<DeleteConflict> deleteConflicts, RequestDetails theRequestDetails) {
|
||||
StopWatch w = new StopWatch();
|
||||
|
||||
Set<Long> resource = processMatchUrl(theUrl, myResourceType);
|
||||
if (resource.size() > 1) {
|
||||
if (myDaoConfig.isAllowMultipleDelete() == false) {
|
||||
|
@ -247,10 +266,10 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
}
|
||||
}
|
||||
|
||||
List<ResourceTable> retVal = new ArrayList<ResourceTable>();
|
||||
List<ResourceTable> deletedResources = new ArrayList<ResourceTable>();
|
||||
for (Long pid : resource) {
|
||||
ResourceTable entity = myEntityManager.find(ResourceTable.class, pid);
|
||||
retVal.add(entity);
|
||||
deletedResources.add(entity);
|
||||
|
||||
validateOkToDelete(deleteConflicts, entity);
|
||||
|
||||
|
@ -274,18 +293,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DaoMethodOutcome deleteByUrl(String theUrl, RequestDetails theRequestDetails) {
|
||||
StopWatch w = new StopWatch();
|
||||
List<DeleteConflict> deleteConflicts = new ArrayList<DeleteConflict>();
|
||||
|
||||
List<ResourceTable> deletedResources = deleteByUrl(theUrl, deleteConflicts, theRequestDetails);
|
||||
|
||||
validateDeleteConflictsEmptyOrThrowException(deleteConflicts);
|
||||
|
||||
IBaseOperationOutcome oo;
|
||||
if (deletedResources.isEmpty()) {
|
||||
oo = OperationOutcomeUtil.newInstance(getContext());
|
||||
|
@ -302,10 +309,23 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
}
|
||||
|
||||
ourLog.info("Processed delete on {} (matched {} resource(s)) in {}ms", new Object[] { theUrl, deletedResources.size(), w.getMillis() });
|
||||
DaoMethodOutcome retVal = new DaoMethodOutcome();
|
||||
|
||||
DeleteMethodOutcome retVal = new DeleteMethodOutcome();
|
||||
retVal.setDeletedEntities(deletedResources);
|
||||
retVal.setOperationOutcome(oo);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeleteMethodOutcome deleteByUrl(String theUrl, RequestDetails theRequestDetails) {
|
||||
List<DeleteConflict> deleteConflicts = new ArrayList<DeleteConflict>();
|
||||
|
||||
DeleteMethodOutcome outcome = deleteByUrl(theUrl, deleteConflicts, theRequestDetails);
|
||||
|
||||
validateDeleteConflictsEmptyOrThrowException(deleteConflicts);
|
||||
|
||||
return outcome;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void detectSearchDaoDisabled() {
|
||||
|
@ -362,6 +382,16 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
updateEntity(theResource, entity, null, thePerformIndexing, thePerformIndexing, theUpdateTime);
|
||||
theResource.setId(entity.getIdDt());
|
||||
|
||||
|
||||
/*
|
||||
* If we aren't indexing (meaning we're probably executing a sub-operation within a transaction),
|
||||
* we'll manually increase the version. This is important because we want the updated version number
|
||||
* to be reflected in the resource shared with interceptors
|
||||
*/
|
||||
if (!thePerformIndexing) {
|
||||
incremenetId(theResource);
|
||||
}
|
||||
|
||||
// Notify JPA interceptors
|
||||
if (theRequestDetails != null) {
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theResource);
|
||||
|
@ -374,6 +404,9 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
}
|
||||
|
||||
DaoMethodOutcome outcome = toMethodOutcome(entity, theResource).setCreated(true);
|
||||
if (!thePerformIndexing) {
|
||||
outcome.setId(theResource.getIdElement());
|
||||
}
|
||||
|
||||
String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulCreate", outcome.getId(), w.getMillisAndRestart());
|
||||
outcome.setOperationOutcome(createInfoOperationOutcome(msg));
|
||||
|
@ -382,6 +415,12 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
return outcome;
|
||||
}
|
||||
|
||||
private void incremenetId(T theResource) {
|
||||
String newVersion = Long.toString(theResource.getIdElement().getVersionIdPartAsLong() + 1);
|
||||
IIdType newId = theResource.getIdElement().withVersion(newVersion);
|
||||
theResource.setId(newId);
|
||||
}
|
||||
|
||||
private <MT extends IBaseMetaType> void doMetaAdd(MT theMetaAdd, BaseHasResource entity) {
|
||||
List<TagDefinition> tags = toTagList(theMetaAdd);
|
||||
|
||||
|
@ -1138,6 +1177,15 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
// Perform update
|
||||
ResourceTable savedEntity = updateEntity(theResource, entity, null, thePerformIndexing, thePerformIndexing, new Date());
|
||||
|
||||
/*
|
||||
* If we aren't indexing (meaning we're probably executing a sub-operation within a transaction),
|
||||
* we'll manually increase the version. This is important because we want the updated version number
|
||||
* to be reflected in the resource shared with interceptors
|
||||
*/
|
||||
if (!thePerformIndexing) {
|
||||
incremenetId(theResource);
|
||||
}
|
||||
|
||||
// Notify interceptors
|
||||
if (theRequestDetails != null) {
|
||||
theRequestDetails.getRequestOperationCallback().resourceUpdated(theResource);
|
||||
|
@ -1150,6 +1198,10 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
DaoMethodOutcome outcome = toMethodOutcome(savedEntity, theResource).setCreated(false);
|
||||
|
||||
if (!thePerformIndexing) {
|
||||
outcome.setId(theResource.getIdElement());
|
||||
}
|
||||
|
||||
String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulCreate", outcome.getId(), w.getMillisAndRestart());
|
||||
outcome.setOperationOutcome(createInfoOperationOutcome(msg));
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
|
||||
/**
|
||||
* This class is a replacement for {@link DaoMethodOutcome} for delete operations,
|
||||
* as they can perform their operation over multiple resources
|
||||
*/
|
||||
public class DeleteMethodOutcome extends MethodOutcome {
|
||||
|
||||
private List<ResourceTable> myDeletedEntities;
|
||||
|
||||
public List<ResourceTable> getDeletedEntities() {
|
||||
return myDeletedEntities;
|
||||
}
|
||||
|
||||
public DeleteMethodOutcome setDeletedEntities(List<ResourceTable> theDeletedEntities) {
|
||||
myDeletedEntities = theDeletedEntities;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -406,14 +406,16 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
|
|||
ca.uhn.fhir.jpa.dao.IFhirResourceDao<? extends IBaseResource> dao = toDao(parts, verb.getCode(), url);
|
||||
int status = Constants.STATUS_HTTP_204_NO_CONTENT;
|
||||
if (parts.getResourceId() != null) {
|
||||
ResourceTable deleted = dao.delete(new IdDt(parts.getResourceType(), parts.getResourceId()), deleteConflicts, theRequestDetails);
|
||||
if (deleted != null) {
|
||||
deletedResources.add(deleted.getIdDt().toUnqualifiedVersionless());
|
||||
DaoMethodOutcome outcome = dao.delete(new IdDt(parts.getResourceType(), parts.getResourceId()), deleteConflicts, theRequestDetails);
|
||||
if (outcome.getEntity() != null) {
|
||||
deletedResources.add(outcome.getId().toUnqualifiedVersionless());
|
||||
entriesToProcess.put(nextRespEntry, outcome.getEntity());
|
||||
}
|
||||
} else {
|
||||
List<ResourceTable> allDeleted = dao.deleteByUrl(parts.getResourceType() + '?' + parts.getParams(), deleteConflicts, theRequestDetails);
|
||||
DeleteMethodOutcome deleteOutcome = dao.deleteByUrl(parts.getResourceType() + '?' + parts.getParams(), deleteConflicts, theRequestDetails);
|
||||
List<ResourceTable> allDeleted = deleteOutcome.getDeletedEntities();
|
||||
for (ResourceTable deleted : allDeleted) {
|
||||
deletedResources.add(deleted.getIdDt().toUnqualifiedVersionless());
|
||||
deletedResources.add(deleted.getIdDt().toUnqualifiedVersionless());
|
||||
}
|
||||
if (allDeleted.isEmpty()) {
|
||||
status = Constants.STATUS_HTTP_404_NOT_FOUND;
|
||||
|
|
|
@ -39,7 +39,6 @@ import ca.uhn.fhir.rest.api.MethodOutcome;
|
|||
import ca.uhn.fhir.rest.api.PatchTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
@ -84,7 +83,7 @@ public interface IFhirResourceDao<T extends IBaseResource> extends IDao {
|
|||
* in the provided list
|
||||
* @param theRequestDetails TODO
|
||||
*/
|
||||
ResourceTable delete(IIdType theResource, List<DeleteConflict> theDeleteConflictsListToPopulate, RequestDetails theRequestDetails);
|
||||
DaoMethodOutcome delete(IIdType theResource, List<DeleteConflict> theDeleteConflictsListToPopulate, RequestDetails theRequestDetails);
|
||||
|
||||
/**
|
||||
* This method throws an exception if there are delete conflicts
|
||||
|
@ -95,12 +94,12 @@ public interface IFhirResourceDao<T extends IBaseResource> extends IDao {
|
|||
* This method does not throw an exception if there are delete conflicts, but populates them
|
||||
* in the provided list
|
||||
*/
|
||||
List<ResourceTable> deleteByUrl(String theUrl, List<DeleteConflict> theDeleteConflictsListToPopulate, RequestDetails theRequestDetails);
|
||||
DeleteMethodOutcome deleteByUrl(String theUrl, List<DeleteConflict> theDeleteConflictsListToPopulate, RequestDetails theRequestDetails);
|
||||
|
||||
/**
|
||||
* This method throws an exception if there are delete conflicts
|
||||
*/
|
||||
DaoMethodOutcome deleteByUrl(String theString, RequestDetails theRequestDetails);
|
||||
DeleteMethodOutcome deleteByUrl(String theString, RequestDetails theRequestDetails);
|
||||
|
||||
TagList getAllResourceTags(RequestDetails theRequestDetails);
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ import com.google.common.collect.ArrayListMultimap;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.dao.DaoMethodOutcome;
|
||||
import ca.uhn.fhir.jpa.dao.DeleteMethodOutcome;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.entity.TagDefinition;
|
||||
|
@ -369,6 +370,12 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
}
|
||||
}
|
||||
|
||||
// } else {
|
||||
//
|
||||
// if (isNotBlank(nextReqEntry.getRequest().getUrl())) {
|
||||
// nextResourceId = new IdType(nextReqEntry.getRequest().getUrl());
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
HTTPVerb verb = nextReqEntry.getRequest().getMethodElement().getValue();
|
||||
|
@ -385,7 +392,9 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
DaoMethodOutcome outcome;
|
||||
String matchUrl = nextReqEntry.getRequest().getIfNoneExist();
|
||||
outcome = resourceDao.create(res, matchUrl, false, theRequestDetails);
|
||||
handleTransactionCreateOrUpdateOutcome(idSubstitutions, idToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res);
|
||||
if (nextResourceId != null) {
|
||||
handleTransactionCreateOrUpdateOutcome(idSubstitutions, idToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res);
|
||||
}
|
||||
entriesToProcess.put(nextRespEntry, outcome.getEntity());
|
||||
if (outcome.getCreated() == false) {
|
||||
nonUpdatedEntities.add(outcome.getEntity());
|
||||
|
@ -402,22 +411,27 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
if (parts.getResourceId() != null) {
|
||||
IdType deleteId = new IdType(parts.getResourceType(), parts.getResourceId());
|
||||
if (!deletedResources.contains(deleteId.getValueAsString())) {
|
||||
ResourceTable deleted = dao.delete(deleteId, deleteConflicts, theRequestDetails);
|
||||
if (deleted != null) {
|
||||
DaoMethodOutcome outcome = dao.delete(deleteId, deleteConflicts, theRequestDetails);
|
||||
if (outcome.getEntity() != null) {
|
||||
deletedResources.add(deleteId.getValueAsString());
|
||||
entriesToProcess.put(nextRespEntry, outcome.getEntity());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
List<ResourceTable> allDeleted = dao.deleteByUrl(parts.getResourceType() + '?' + parts.getParams(), deleteConflicts, theRequestDetails);
|
||||
DeleteMethodOutcome deleteOutcome = dao.deleteByUrl(parts.getResourceType() + '?' + parts.getParams(), deleteConflicts, theRequestDetails);
|
||||
List<ResourceTable> allDeleted = deleteOutcome.getDeletedEntities();
|
||||
for (ResourceTable deleted : allDeleted) {
|
||||
deletedResources.add(deleted.getIdDt().toUnqualifiedVersionless().getValueAsString());
|
||||
}
|
||||
if (allDeleted.isEmpty()) {
|
||||
status = Constants.STATUS_HTTP_204_NO_CONTENT;
|
||||
}
|
||||
|
||||
nextRespEntry.getResponse().setOutcome((Resource) deleteOutcome.getOperationOutcome());
|
||||
}
|
||||
|
||||
nextRespEntry.getResponse().setStatus(toStatusString(status));
|
||||
|
||||
break;
|
||||
}
|
||||
case PUT: {
|
||||
|
@ -630,7 +644,7 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
}
|
||||
|
||||
private static boolean isPlaceholder(IdType theId) {
|
||||
if (theId.getValue() != null) {
|
||||
if (theId != null && theId.getValue() != null) {
|
||||
if (theId.getValue().startsWith("urn:oid:") || theId.getValue().startsWith("urn:uuid:")) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -67,12 +67,15 @@ public abstract class BaseJpaTest {
|
|||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseJpaTest.class);
|
||||
protected ServletRequestDetails mySrd;
|
||||
protected ArrayList<IServerInterceptor> myServerInterceptorList;
|
||||
protected IRequestOperationCallback myRequestOperationCallback = mock(IRequestOperationCallback.class);
|
||||
|
||||
@Before
|
||||
public void beforeCreateSrd() {
|
||||
mySrd = mock(ServletRequestDetails.class, Mockito.RETURNS_DEEP_STUBS);
|
||||
when(mySrd.getRequestOperationCallback()).thenReturn(mock(IRequestOperationCallback.class));
|
||||
when(mySrd.getServer().getInterceptors()).thenReturn(new ArrayList<IServerInterceptor>());
|
||||
when(mySrd.getRequestOperationCallback()).thenReturn(myRequestOperationCallback);
|
||||
myServerInterceptorList = new ArrayList<IServerInterceptor>();
|
||||
when(mySrd.getServer().getInterceptors()).thenReturn(myServerInterceptorList);
|
||||
when(mySrd.getUserData()).thenReturn(new HashMap<Object, Object>());
|
||||
}
|
||||
|
||||
|
|
|
@ -1,58 +1,65 @@
|
|||
package ca.uhn.fhir.jpa.dao.dstu2;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
|
||||
import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.DaoMethodOutcome;
|
||||
import ca.uhn.fhir.jpa.dao.DeleteMethodOutcome;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.interceptor.IJpaServerInterceptor;
|
||||
import ca.uhn.fhir.jpa.interceptor.JpaServerInterceptorAdapter;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class FhirResourceDaoDstu2InterceptorTest extends BaseJpaDstu2Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu2InterceptorTest.class);
|
||||
private IJpaServerInterceptor myJpaInterceptor;
|
||||
private JpaServerInterceptorAdapter myJpaInterceptorAdapter = new JpaServerInterceptorAdapter();
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
myDaoConfig.getInterceptors().remove(myJpaInterceptor);
|
||||
myDaoConfig.getInterceptors().remove(myJpaInterceptorAdapter);
|
||||
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
|
||||
}
|
||||
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
myJpaInterceptor = mock(IJpaServerInterceptor.class);
|
||||
myDaoConfig.getInterceptors().add(myJpaInterceptor);
|
||||
myDaoConfig.getInterceptors().add(myJpaInterceptorAdapter);
|
||||
}
|
||||
|
||||
/*
|
||||
* *****************************************************
|
||||
* Note that non JPA specific operations get tested in individual
|
||||
* operation test methods too
|
||||
* *****************************************************
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testJpaCreate() {
|
||||
Patient p = new Patient();
|
||||
|
@ -86,7 +93,7 @@ public class FhirResourceDaoDstu2InterceptorTest extends BaseJpaDstu2Test {
|
|||
verify(myJpaInterceptor, times(0)).resourceUpdated(detailsCapt.capture(), tableCapt.capture());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testJpaDelete() {
|
||||
Patient p = new Patient();
|
||||
|
@ -106,6 +113,12 @@ public class FhirResourceDaoDstu2InterceptorTest extends BaseJpaDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
* *****************************************************
|
||||
* Note that non JPA specific operations get tested in individual
|
||||
* operation test methods too
|
||||
* *****************************************************
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testJpaUpdate() {
|
||||
|
@ -162,4 +175,247 @@ public class FhirResourceDaoDstu2InterceptorTest extends BaseJpaDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestOperationCreate() {
|
||||
IServerOperationInterceptor interceptor = mock(IServerOperationInterceptor.class);
|
||||
myServerInterceptorList.add(interceptor);
|
||||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[0];
|
||||
Long id = res.getIdElement().getIdPartAsLong();
|
||||
assertEquals("Patient/" + id + "/_history/1", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceCreated(any(IBaseResource.class));
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("PATIENT");
|
||||
IIdType id = myPatientDao.create(p, mySrd).getId();
|
||||
assertEquals(1L, id.getVersionIdPartAsLong().longValue());
|
||||
|
||||
verify(myRequestOperationCallback, times(1)).resourceCreated(any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRequestOperationDelete() {
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("PATIENT");
|
||||
Long id = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[0];
|
||||
Long id = res.getIdElement().getIdPartAsLong();
|
||||
assertEquals("Patient/" + id + "/_history/2", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceDeleted(any(IBaseResource.class));
|
||||
|
||||
IIdType newId = myPatientDao.delete(new IdDt("Patient/" + id), mySrd).getId();
|
||||
assertEquals(2L, newId.getVersionIdPartAsLong().longValue());
|
||||
|
||||
verify(myRequestOperationCallback, times(1)).resourceDeleted(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(1)).resourceCreated(any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testRequestOperationDeleteMulti() {
|
||||
myDaoConfig.setAllowMultipleDelete(true);
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("PATIENT");
|
||||
Long id = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
p = new Patient();
|
||||
p.addName().addFamily("PATIENT");
|
||||
Long id2 = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[0];
|
||||
Long id = res.getIdElement().getIdPartAsLong();
|
||||
assertEquals("Patient/" + id + "/_history/2", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceDeleted(any(IBaseResource.class));
|
||||
|
||||
DeleteMethodOutcome outcome = myPatientDao.deleteByUrl("Patient?name=PATIENT", mySrd);
|
||||
String oo = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(outcome.getOperationOutcome());
|
||||
ourLog.info(oo);
|
||||
assertThat(oo, containsString("deleted 2 resource(s)"));
|
||||
|
||||
verify(myRequestOperationCallback, times(2)).resourceDeleted(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(2)).resourceCreated(any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestOperationTransactionCreate() {
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("PATIENT");
|
||||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[0];
|
||||
Long id = res.getIdElement().getIdPartAsLong();
|
||||
assertEquals("Patient/" + id + "/_history/1", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceCreated(any(IBaseResource.class));
|
||||
|
||||
Bundle xactBundle = new Bundle();
|
||||
xactBundle.setType(BundleTypeEnum.TRANSACTION);
|
||||
xactBundle
|
||||
.addEntry()
|
||||
.setResource(p)
|
||||
.getRequest()
|
||||
.setUrl("Patient")
|
||||
.setMethod(HTTPVerbEnum.POST);
|
||||
Bundle resp = mySystemDao.transaction(mySrd, xactBundle);
|
||||
|
||||
IdDt newId = new IdDt(resp.getEntry().get(0).getResponse().getLocation());
|
||||
assertEquals(1L, newId.getVersionIdPartAsLong().longValue());
|
||||
|
||||
verify(myRequestOperationCallback, times(1)).resourceCreated(any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestOperationTransactionDelete() {
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("PATIENT");
|
||||
Long id = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[0];
|
||||
Long id = res.getIdElement().getIdPartAsLong();
|
||||
assertEquals("Patient/" + id + "/_history/2", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceDeleted(any(IBaseResource.class));
|
||||
|
||||
Bundle xactBundle = new Bundle();
|
||||
xactBundle.setType(BundleTypeEnum.TRANSACTION);
|
||||
xactBundle
|
||||
.addEntry()
|
||||
.getRequest()
|
||||
.setUrl("Patient/" + id)
|
||||
.setMethod(HTTPVerbEnum.DELETE);
|
||||
Bundle resp = mySystemDao.transaction(mySrd, xactBundle);
|
||||
|
||||
IdDt newId = new IdDt(resp.getEntry().get(0).getResponse().getLocation());
|
||||
assertEquals(2L, newId.getVersionIdPartAsLong().longValue());
|
||||
|
||||
verify(myRequestOperationCallback, times(1)).resourceDeleted(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(1)).resourceCreated(any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestOperationTransactionDeleteMulti() {
|
||||
myDaoConfig.setAllowMultipleDelete(true);
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("PATIENT");
|
||||
Long id = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
p = new Patient();
|
||||
p.addName().addFamily("PATIENT");
|
||||
Long id2 = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[0];
|
||||
Long id = res.getIdElement().getIdPartAsLong();
|
||||
assertEquals("Patient/" + id + "/_history/2", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceDeleted(any(IBaseResource.class));
|
||||
|
||||
Bundle xactBundle = new Bundle();
|
||||
xactBundle.setType(BundleTypeEnum.TRANSACTION);
|
||||
xactBundle
|
||||
.addEntry()
|
||||
.getRequest()
|
||||
.setUrl("Patient?name=PATIENT")
|
||||
.setMethod(HTTPVerbEnum.DELETE);
|
||||
Bundle resp = mySystemDao.transaction(mySrd, xactBundle);
|
||||
|
||||
verify(myRequestOperationCallback, times(2)).resourceDeleted(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(2)).resourceCreated(any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestOperationTransactionUpdate() {
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("PATIENT");
|
||||
final Long id = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
p = new Patient();
|
||||
p.setId(new IdDt("Patient/" + id));
|
||||
p.addName().addFamily("PATIENT2");
|
||||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[0];
|
||||
assertEquals("Patient/" + id + "/_history/2", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceUpdated(any(IBaseResource.class));
|
||||
|
||||
Bundle xactBundle = new Bundle();
|
||||
xactBundle.setType(BundleTypeEnum.TRANSACTION);
|
||||
xactBundle
|
||||
.addEntry()
|
||||
.setResource(p)
|
||||
.getRequest()
|
||||
.setUrl("Patient/" + id)
|
||||
.setMethod(HTTPVerbEnum.PUT);
|
||||
Bundle resp = mySystemDao.transaction(mySrd, xactBundle);
|
||||
|
||||
IdDt newId = new IdDt(resp.getEntry().get(0).getResponse().getLocation());
|
||||
assertEquals(2L, newId.getVersionIdPartAsLong().longValue());
|
||||
|
||||
verify(myRequestOperationCallback, times(1)).resourceUpdated(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(1)).resourceCreated(any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestOperationUpdate() {
|
||||
Patient p = new Patient();
|
||||
p.addName().addFamily("PATIENT");
|
||||
final Long id = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[0];
|
||||
assertEquals("Patient/" + id + "/_history/2", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceUpdated(any(IBaseResource.class));
|
||||
|
||||
p = new Patient();
|
||||
p.setId(new IdDt("Patient/" + id));
|
||||
p.addName().addFamily("PATIENT2");
|
||||
IIdType newId = myPatientDao.update(p, mySrd).getId();
|
||||
assertEquals(2L, newId.getVersionIdPartAsLong().longValue());
|
||||
|
||||
verify(myRequestOperationCallback, times(1)).resourceUpdated(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(1)).resourceCreated(any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,78 +1,87 @@
|
|||
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.hl7.fhir.dstu3.model.Bundle;
|
||||
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
|
||||
import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb;
|
||||
import org.hl7.fhir.dstu3.model.IdType;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.DaoMethodOutcome;
|
||||
import ca.uhn.fhir.jpa.dao.DeleteMethodOutcome;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.interceptor.IJpaServerInterceptor;
|
||||
import ca.uhn.fhir.jpa.interceptor.JpaServerInterceptorAdapter;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class FhirResourceDaoDstu3InterceptorTest extends BaseJpaDstu3Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3InterceptorTest.class);
|
||||
private IJpaServerInterceptor myJpaInterceptor;
|
||||
private JpaServerInterceptorAdapter myJpaInterceptorAdapter = new JpaServerInterceptorAdapter();
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
myDaoConfig.getInterceptors().remove(myJpaInterceptor);
|
||||
myDaoConfig.getInterceptors().remove(myJpaInterceptorAdapter);
|
||||
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
|
||||
}
|
||||
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
myJpaInterceptor = mock(IJpaServerInterceptor.class);
|
||||
myDaoConfig.getInterceptors().add(myJpaInterceptor);
|
||||
myDaoConfig.getInterceptors().add(myJpaInterceptorAdapter);
|
||||
}
|
||||
|
||||
/*
|
||||
* *****************************************************
|
||||
* Note that non JPA specific operations get tested in individual
|
||||
* operation test methods too
|
||||
* *****************************************************
|
||||
*/
|
||||
|
||||
|
||||
@Test
|
||||
public void testJpaCreate() {
|
||||
Patient p = new Patient();
|
||||
p.addName().setFamily("PATIENT");
|
||||
Long id = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
|
||||
ArgumentCaptor<ActionRequestDetails> detailsCapt;
|
||||
ArgumentCaptor<ResourceTable> tableCapt;
|
||||
|
||||
|
||||
detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
||||
tableCapt = ArgumentCaptor.forClass(ResourceTable.class);
|
||||
verify(myJpaInterceptor, times(1)).resourceCreated(detailsCapt.capture(), tableCapt.capture());
|
||||
assertNotNull(tableCapt.getValue().getId());
|
||||
assertEquals(id, tableCapt.getValue().getId());
|
||||
|
||||
|
||||
detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
||||
tableCapt = ArgumentCaptor.forClass(ResourceTable.class);
|
||||
verify(myJpaInterceptor, times(0)).resourceUpdated(detailsCapt.capture(), tableCapt.capture());
|
||||
|
||||
|
||||
/*
|
||||
* Not do a conditional create
|
||||
*/
|
||||
|
@ -88,6 +97,13 @@ public class FhirResourceDaoDstu3InterceptorTest extends BaseJpaDstu3Test {
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
* *****************************************************
|
||||
* Note that non JPA specific operations get tested in individual
|
||||
* operation test methods too
|
||||
* *****************************************************
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testJpaDelete() {
|
||||
Patient p = new Patient();
|
||||
|
@ -95,19 +111,18 @@ public class FhirResourceDaoDstu3InterceptorTest extends BaseJpaDstu3Test {
|
|||
Long id = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
myPatientDao.delete(new IdType("Patient", id), mySrd);
|
||||
|
||||
|
||||
ArgumentCaptor<ActionRequestDetails> detailsCapt;
|
||||
ArgumentCaptor<ResourceTable> tableCapt;
|
||||
|
||||
|
||||
detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
||||
tableCapt = ArgumentCaptor.forClass(ResourceTable.class);
|
||||
verify(myJpaInterceptor, times(1)).resourceDeleted(detailsCapt.capture(), tableCapt.capture());
|
||||
assertNotNull(tableCapt.getValue().getId());
|
||||
assertEquals(id, tableCapt.getValue().getId());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testJpaUpdate() {
|
||||
Patient p = new Patient();
|
||||
|
@ -122,13 +137,13 @@ public class FhirResourceDaoDstu3InterceptorTest extends BaseJpaDstu3Test {
|
|||
|
||||
ArgumentCaptor<ActionRequestDetails> detailsCapt;
|
||||
ArgumentCaptor<ResourceTable> tableCapt;
|
||||
|
||||
|
||||
detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
||||
tableCapt = ArgumentCaptor.forClass(ResourceTable.class);
|
||||
verify(myJpaInterceptor, times(1)).resourceUpdated(detailsCapt.capture(), tableCapt.capture());
|
||||
assertNotNull(tableCapt.getValue().getId());
|
||||
assertEquals(id, tableCapt.getValue().getId());
|
||||
|
||||
|
||||
/*
|
||||
* Now do a conditional update
|
||||
*/
|
||||
|
@ -160,7 +175,251 @@ public class FhirResourceDaoDstu3InterceptorTest extends BaseJpaDstu3Test {
|
|||
verify(myJpaInterceptor, times(2)).resourceCreated(detailsCapt.capture(), tableCapt.capture());
|
||||
assertEquals(id2, tableCapt.getAllValues().get(3).getId());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestOperationCreate() {
|
||||
IServerOperationInterceptor interceptor = mock(IServerOperationInterceptor.class);
|
||||
myServerInterceptorList.add(interceptor);
|
||||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[0];
|
||||
Long id = res.getIdElement().getIdPartAsLong();
|
||||
assertEquals("Patient/" + id + "/_history/1", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceCreated(any(IBaseResource.class));
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().setFamily("PATIENT");
|
||||
IIdType id = myPatientDao.create(p, mySrd).getId();
|
||||
assertEquals(1L, id.getVersionIdPartAsLong().longValue());
|
||||
|
||||
verify(myRequestOperationCallback, times(1)).resourceCreated(any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestOperationDelete() {
|
||||
Patient p = new Patient();
|
||||
p.addName().setFamily("PATIENT");
|
||||
Long id = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[0];
|
||||
Long id = res.getIdElement().getIdPartAsLong();
|
||||
assertEquals("Patient/" + id + "/_history/2", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceDeleted(any(IBaseResource.class));
|
||||
|
||||
IIdType newId = myPatientDao.delete(new IdType("Patient/" + id), mySrd).getId();
|
||||
assertEquals(2L, newId.getVersionIdPartAsLong().longValue());
|
||||
|
||||
verify(myRequestOperationCallback, times(1)).resourceDeleted(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(1)).resourceCreated(any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestOperationDeleteMulti() {
|
||||
myDaoConfig.setAllowMultipleDelete(true);
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().setFamily("PATIENT");
|
||||
Long id = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
p = new Patient();
|
||||
p.addName().setFamily("PATIENT");
|
||||
Long id2 = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[0];
|
||||
Long id = res.getIdElement().getIdPartAsLong();
|
||||
assertEquals("Patient/" + id + "/_history/2", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceDeleted(any(IBaseResource.class));
|
||||
|
||||
DeleteMethodOutcome outcome = myPatientDao.deleteByUrl("Patient?name=PATIENT", mySrd);
|
||||
String oo = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(outcome.getOperationOutcome());
|
||||
ourLog.info(oo);
|
||||
assertThat(oo, containsString("deleted 2 resource(s)"));
|
||||
|
||||
verify(myRequestOperationCallback, times(2)).resourceDeleted(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(2)).resourceCreated(any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestOperationTransactionCreate() {
|
||||
Patient p = new Patient();
|
||||
p.addName().setFamily("PATIENT");
|
||||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[0];
|
||||
Long id = res.getIdElement().getIdPartAsLong();
|
||||
assertEquals("Patient/" + id + "/_history/1", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceCreated(any(IBaseResource.class));
|
||||
|
||||
Bundle xactBundle = new Bundle();
|
||||
xactBundle.setType(BundleType.TRANSACTION);
|
||||
xactBundle
|
||||
.addEntry()
|
||||
.setResource(p)
|
||||
.getRequest()
|
||||
.setUrl("Patient")
|
||||
.setMethod(HTTPVerb.POST);
|
||||
Bundle resp = mySystemDao.transaction(mySrd, xactBundle);
|
||||
|
||||
IdType newId = new IdType(resp.getEntry().get(0).getResponse().getLocation());
|
||||
assertEquals(1L, newId.getVersionIdPartAsLong().longValue());
|
||||
|
||||
verify(myRequestOperationCallback, times(1)).resourceCreated(any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestOperationTransactionDelete() {
|
||||
Patient p = new Patient();
|
||||
p.addName().setFamily("PATIENT");
|
||||
Long id = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[0];
|
||||
Long id = res.getIdElement().getIdPartAsLong();
|
||||
assertEquals("Patient/" + id + "/_history/2", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceDeleted(any(IBaseResource.class));
|
||||
|
||||
Bundle xactBundle = new Bundle();
|
||||
xactBundle.setType(BundleType.TRANSACTION);
|
||||
xactBundle
|
||||
.addEntry()
|
||||
.getRequest()
|
||||
.setUrl("Patient/" + id)
|
||||
.setMethod(HTTPVerb.DELETE);
|
||||
Bundle resp = mySystemDao.transaction(mySrd, xactBundle);
|
||||
|
||||
IdType newId = new IdType(resp.getEntry().get(0).getResponse().getLocation());
|
||||
assertEquals(2L, newId.getVersionIdPartAsLong().longValue());
|
||||
|
||||
verify(myRequestOperationCallback, times(1)).resourceDeleted(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(1)).resourceCreated(any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestOperationTransactionDeleteMulti() {
|
||||
myDaoConfig.setAllowMultipleDelete(true);
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().setFamily("PATIENT");
|
||||
Long id = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
p = new Patient();
|
||||
p.addName().setFamily("PATIENT");
|
||||
Long id2 = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[0];
|
||||
Long id = res.getIdElement().getIdPartAsLong();
|
||||
assertEquals("Patient/" + id + "/_history/2", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceDeleted(any(IBaseResource.class));
|
||||
|
||||
Bundle xactBundle = new Bundle();
|
||||
xactBundle.setType(BundleType.TRANSACTION);
|
||||
xactBundle
|
||||
.addEntry()
|
||||
.getRequest()
|
||||
.setUrl("Patient?name=PATIENT")
|
||||
.setMethod(HTTPVerb.DELETE);
|
||||
Bundle resp = mySystemDao.transaction(mySrd, xactBundle);
|
||||
|
||||
String oo = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp);
|
||||
ourLog.info(oo);
|
||||
assertThat(oo, containsString("deleted 2 resource(s)"));
|
||||
|
||||
verify(myRequestOperationCallback, times(2)).resourceDeleted(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(2)).resourceCreated(any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestOperationTransactionUpdate() {
|
||||
Patient p = new Patient();
|
||||
p.addName().setFamily("PATIENT");
|
||||
final Long id = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
p = new Patient();
|
||||
p.setId(new IdType("Patient/" + id));
|
||||
p.addName().setFamily("PATIENT2");
|
||||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[0];
|
||||
assertEquals("Patient/" + id + "/_history/2", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceUpdated(any(IBaseResource.class));
|
||||
|
||||
Bundle xactBundle = new Bundle();
|
||||
xactBundle.setType(BundleType.TRANSACTION);
|
||||
xactBundle
|
||||
.addEntry()
|
||||
.setResource(p)
|
||||
.getRequest()
|
||||
.setUrl("Patient/" + id)
|
||||
.setMethod(HTTPVerb.PUT);
|
||||
Bundle resp = mySystemDao.transaction(mySrd, xactBundle);
|
||||
|
||||
IdType newId = new IdType(resp.getEntry().get(0).getResponse().getLocation());
|
||||
assertEquals(2L, newId.getVersionIdPartAsLong().longValue());
|
||||
|
||||
verify(myRequestOperationCallback, times(1)).resourceUpdated(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(1)).resourceCreated(any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestOperationUpdate() {
|
||||
Patient p = new Patient();
|
||||
p.addName().setFamily("PATIENT");
|
||||
final Long id = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[0];
|
||||
assertEquals("Patient/" + id + "/_history/2", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceUpdated(any(IBaseResource.class));
|
||||
|
||||
p = new Patient();
|
||||
p.setId(new IdType("Patient/" + id));
|
||||
p.addName().setFamily("PATIENT2");
|
||||
IIdType newId = myPatientDao.update(p, mySrd).getId();
|
||||
assertEquals(2L, newId.getVersionIdPartAsLong().longValue());
|
||||
|
||||
verify(myRequestOperationCallback, times(1)).resourceUpdated(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(1)).resourceCreated(any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -162,6 +162,10 @@
|
|||
occur under certain circumstances when the response contained
|
||||
contained resources
|
||||
</action>
|
||||
<action type="fix">
|
||||
JPA server interceptor methods for create/update/delete provided
|
||||
the wrong version ID to the interceptors
|
||||
</action>
|
||||
</release>
|
||||
<release version="2.2" date="2016-12-20">
|
||||
<action type="add">
|
||||
|
|
Loading…
Reference in New Issue