Added new callbacks to IServerOperationInterceptor to be invoked before
other operation methods
This commit is contained in:
parent
fe37c87e78
commit
b18e71d4f5
|
@ -196,6 +196,16 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
T resourceToDelete = toResource(myResourceType, entity, false);
|
||||
|
||||
// Notify IServerOperationInterceptors about pre-action call
|
||||
if (theRequestDetails != null) {
|
||||
theRequestDetails.getRequestOperationCallback().resourcePreDelete(resourceToDelete);
|
||||
}
|
||||
for (IServerInterceptor next : getConfig().getInterceptors()) {
|
||||
if (next instanceof IServerOperationInterceptor) {
|
||||
((IServerOperationInterceptor) next).resourcePreDelete(theRequestDetails, resourceToDelete);
|
||||
}
|
||||
}
|
||||
|
||||
validateOkToDelete(theDeleteConflicts, entity);
|
||||
|
||||
preDelete(resourceToDelete, entity);
|
||||
|
@ -267,6 +277,17 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
deletedResources.add(entity);
|
||||
|
||||
T resourceToDelete = toResource(myResourceType, entity, false);
|
||||
|
||||
// Notify IServerOperationInterceptors about pre-action call
|
||||
if (theRequestDetails != null) {
|
||||
theRequestDetails.getRequestOperationCallback().resourcePreDelete(resourceToDelete);
|
||||
}
|
||||
for (IServerInterceptor next : getConfig().getInterceptors()) {
|
||||
if (next instanceof IServerOperationInterceptor) {
|
||||
((IServerOperationInterceptor) next).resourcePreDelete(theRequestDetails, resourceToDelete);
|
||||
}
|
||||
}
|
||||
|
||||
validateOkToDelete(deleteConflicts, entity);
|
||||
|
||||
// Notify interceptors
|
||||
|
@ -378,6 +399,16 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
notifyInterceptors(RestOperationTypeEnum.CREATE, requestDetails);
|
||||
}
|
||||
|
||||
// Notify JPA interceptors
|
||||
if (theRequestDetails != null) {
|
||||
theRequestDetails.getRequestOperationCallback().resourcePreCreate(theResource);
|
||||
}
|
||||
for (IServerInterceptor next : getConfig().getInterceptors()) {
|
||||
if (next instanceof IServerOperationInterceptor) {
|
||||
((IServerOperationInterceptor) next).resourcePreCreate(theRequestDetails, theResource);
|
||||
}
|
||||
}
|
||||
|
||||
// Perform actual DB update
|
||||
updateEntity(theResource, entity, null, thePerformIndexing, thePerformIndexing, theUpdateTime, false, thePerformIndexing);
|
||||
theResource.setId(entity.getIdDt());
|
||||
|
@ -558,10 +589,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
if (theRequestDetails == null || theRequestDetails.getServer() == null) {
|
||||
return false;
|
||||
}
|
||||
if (theRequestDetails.getServer().getPagingProvider() instanceof DatabaseBackedPagingProvider) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return theRequestDetails.getServer().getPagingProvider() instanceof DatabaseBackedPagingProvider;
|
||||
}
|
||||
|
||||
protected void markResourcesMatchingExpressionAsNeedingReindexing(String theExpression) {
|
||||
|
@ -816,9 +844,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
@Override
|
||||
public BaseHasResource readEntity(IIdType theId) {
|
||||
boolean checkForForcedId = true;
|
||||
|
||||
BaseHasResource entity = readEntity(theId, checkForForcedId);
|
||||
BaseHasResource entity = readEntity(theId, true);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
@ -1048,7 +1074,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
if (theResource instanceof IResource) {
|
||||
ResourceMetadataKeyEnum.UPDATED.put((IResource) theResource, theEntity.getUpdated());
|
||||
} else {
|
||||
IBaseMetaType meta = ((IAnyResource) theResource).getMeta();
|
||||
IBaseMetaType meta = theResource.getMeta();
|
||||
meta.setLastUpdated(theEntity.getUpdatedDate());
|
||||
}
|
||||
}
|
||||
|
@ -1183,8 +1209,17 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
IBaseResource oldResource = toResource(entity, false);
|
||||
|
||||
// Notify IServerOperationInterceptors about pre-action call
|
||||
if (theRequestDetails != null) {
|
||||
theRequestDetails.getRequestOperationCallback().resourcePreUpdate(oldResource, theResource);
|
||||
}
|
||||
for (IServerInterceptor next : getConfig().getInterceptors()) {
|
||||
if (next instanceof IServerOperationInterceptor) {
|
||||
((IServerOperationInterceptor) next).resourcePreUpdate(theRequestDetails, oldResource, theResource);
|
||||
}
|
||||
}
|
||||
|
||||
// Perform update
|
||||
StopWatch sw = new StopWatch();
|
||||
ResourceTable savedEntity = updateEntity(theResource, entity, null, thePerformIndexing, thePerformIndexing, new Date(), theForceUpdateVersion, thePerformIndexing);
|
||||
|
||||
/*
|
||||
|
|
|
@ -18,10 +18,14 @@ import org.junit.AfterClass;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.any;
|
||||
|
@ -32,6 +36,7 @@ public class FhirResourceDaoR4InterceptorTest extends BaseJpaR4Test {
|
|||
private IServerOperationInterceptor myJpaInterceptor;
|
||||
private ServerOperationInterceptorAdapter myJpaInterceptorAdapter = new ServerOperationInterceptorAdapter();
|
||||
private IServerOperationInterceptor myServerOperationInterceptor;
|
||||
private List<IIdType> myIds = new ArrayList<>();
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
|
@ -43,10 +48,11 @@ public class FhirResourceDaoR4InterceptorTest extends BaseJpaR4Test {
|
|||
@Before
|
||||
public void before() {
|
||||
myJpaInterceptor = mock(IServerOperationInterceptor.class);
|
||||
myIds.clear();
|
||||
|
||||
myServerOperationInterceptor = mock(IServerOperationInterceptor.class, new Answer<Object>() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
public Object answer(InvocationOnMock theInvocation) {
|
||||
if (theInvocation.getMethod().getReturnType().equals(boolean.class)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -180,22 +186,265 @@ public class FhirResourceDaoR4InterceptorTest extends BaseJpaR4Test {
|
|||
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
public Void answer(InvocationOnMock theInvocation) {
|
||||
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));
|
||||
}
|
||||
}).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)).resourcePreCreate(any(IBaseResource.class));
|
||||
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) {
|
||||
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)).resourcePreDelete(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(1)).resourcePreCreate(any(IBaseResource.class));
|
||||
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) {
|
||||
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));
|
||||
verify(myRequestOperationCallback, times(2)).resourcePreDelete(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(2)).resourcePreCreate(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) {
|
||||
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));
|
||||
verify(myRequestOperationCallback, times(1)).resourcePreCreate(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) {
|
||||
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)).resourcePreDelete(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(1)).resourcePreCreate(any(IBaseResource.class));
|
||||
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) {
|
||||
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));
|
||||
verify(myRequestOperationCallback, times(2)).resourcePreDelete(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(2)).resourcePreCreate(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) {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[1];
|
||||
assertEquals("Patient/" + id + "/_history/2", res.getIdElement().getValue());
|
||||
return null;
|
||||
}
|
||||
}).when(myRequestOperationCallback).resourceUpdated(any(IBaseResource.class), 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)).resourceUpdated(any(IBaseResource.class), any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(1)).resourceCreated(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(1)).resourcePreCreate(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(1)).resourcePreUpdate(any(IBaseResource.class), 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) {
|
||||
IBaseResource res = (IBaseResource) theInvocation.getArguments()[0];
|
||||
assertEquals("Patient/" + id + "/_history/1", res.getIdElement().getValue());
|
||||
res = (IBaseResource) theInvocation.getArguments()[1];
|
||||
assertEquals("Patient/" + id + "/_history/2", res.getIdElement().getValue());
|
||||
return null;
|
||||
}
|
||||
}).when(myRequestOperationCallback).resourceUpdated(any(IBaseResource.class), 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)).resourceUpdated(any(IBaseResource.class), any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(1)).resourceCreated(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(1)).resourcePreCreate(any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(1)).resourcePreUpdate(any(IBaseResource.class), any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerOperationCreate() {
|
||||
verify(myServerOperationInterceptor, times(0)).resourceCreated(Mockito.isNull(RequestDetails.class), any(IBaseResource.class));
|
||||
|
@ -208,6 +457,138 @@ public class FhirResourceDaoR4InterceptorTest extends BaseJpaR4Test {
|
|||
verify(myServerOperationInterceptor, times(1)).resourceCreated(Mockito.isNull(RequestDetails.class), any(IBaseResource.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerOperationDelete() {
|
||||
verify(myServerOperationInterceptor, times(0)).resourceCreated(Mockito.isNull(RequestDetails.class), any(IBaseResource.class));
|
||||
verify(myServerOperationInterceptor, times(0)).resourceDeleted(Mockito.isNull(RequestDetails.class), any(IBaseResource.class));
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().setFamily("PATIENT");
|
||||
IIdType id = myPatientDao.create(p, (RequestDetails) null).getId();
|
||||
assertEquals(1L, id.getVersionIdPartAsLong().longValue());
|
||||
|
||||
p.addName().setFamily("2");
|
||||
myPatientDao.delete(p.getIdElement().toUnqualifiedVersionless());
|
||||
|
||||
verify(myServerOperationInterceptor, times(1)).resourceCreated(Mockito.isNull(RequestDetails.class), any(IBaseResource.class));
|
||||
verify(myServerOperationInterceptor, times(1)).resourceDeleted(Mockito.isNull(RequestDetails.class), any(IBaseResource.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerOperationInterceptorCanModifyOnCreate() {
|
||||
|
||||
ServerOperationInterceptorAdapter interceptor = new ServerOperationInterceptorAdapter() {
|
||||
@Override
|
||||
public void resourcePreCreate(RequestDetails theRequest, IBaseResource theResource) {
|
||||
((Patient) theResource).setActive(true);
|
||||
}
|
||||
};
|
||||
myDaoConfig.getInterceptors().add(interceptor);
|
||||
try {
|
||||
|
||||
doAnswer(new MyOneResourceAnswer()).when(myJpaInterceptor).resourcePreCreate(any(RequestDetails.class), any(IBaseResource.class));
|
||||
doAnswer(new MyOneResourceAnswer()).when(myJpaInterceptor).resourceCreated(any(RequestDetails.class), any(IBaseResource.class));
|
||||
|
||||
Patient p = new Patient();
|
||||
p.setActive(false);
|
||||
IIdType id = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
InOrder inorder = inOrder(myJpaInterceptor, myRequestOperationCallback);
|
||||
inorder.verify(myRequestOperationCallback, times(1)).resourcePreCreate(any(IBaseResource.class));
|
||||
inorder.verify(myJpaInterceptor, times(1)).resourcePreCreate(any(RequestDetails.class), any(IBaseResource.class));
|
||||
inorder.verify(myRequestOperationCallback, times(1)).resourceCreated(any(IBaseResource.class));
|
||||
inorder.verify(myJpaInterceptor, times(1)).resourceCreated(any(RequestDetails.class), any(IBaseResource.class));
|
||||
|
||||
assertNull(myIds.get(0).getIdPart());
|
||||
assertNull(myIds.get(0).getVersionIdPart());
|
||||
assertNotNull(myIds.get(1).getIdPart());
|
||||
assertEquals("1", myIds.get(1).getVersionIdPart());
|
||||
|
||||
p = myPatientDao.read(id);
|
||||
assertEquals(true, p.getActive());
|
||||
|
||||
} finally {
|
||||
myDaoConfig.getInterceptors().remove(interceptor);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerOperationInterceptorCanModifyOnUpdate() {
|
||||
|
||||
ServerOperationInterceptorAdapter interceptor = new ServerOperationInterceptorAdapter() {
|
||||
@Override
|
||||
public void resourcePreUpdate(RequestDetails theRequest, IBaseResource theOldResource, IBaseResource theNewResource) {
|
||||
((Patient) theNewResource).setActive(true);
|
||||
}
|
||||
};
|
||||
myDaoConfig.getInterceptors().add(interceptor);
|
||||
try {
|
||||
|
||||
doAnswer(new MyTwoResourceAnswer()).when(myJpaInterceptor).resourcePreUpdate(any(RequestDetails.class), any(IBaseResource.class), any(IBaseResource.class));
|
||||
doAnswer(new MyTwoResourceAnswer()).when(myJpaInterceptor).resourceUpdated(any(RequestDetails.class), any(IBaseResource.class), any(IBaseResource.class));
|
||||
|
||||
Patient p = new Patient();
|
||||
p.setActive(false);
|
||||
IIdType id = myPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||
String idPart = id.getIdPart();
|
||||
|
||||
p = myPatientDao.read(id);
|
||||
assertEquals(false, p.getActive());
|
||||
|
||||
p.setId(p.getIdElement().toUnqualifiedVersionless());
|
||||
p.addAddress().setCity("CITY");
|
||||
myPatientDao.update(p, mySrd);
|
||||
|
||||
InOrder inorder = inOrder(myJpaInterceptor, myRequestOperationCallback);
|
||||
inorder.verify(myRequestOperationCallback, times(1)).resourcePreUpdate(any(IBaseResource.class), any(IBaseResource.class));
|
||||
inorder.verify(myJpaInterceptor, times(1)).resourcePreUpdate(any(RequestDetails.class), any(IBaseResource.class), any(IBaseResource.class));
|
||||
inorder.verify(myRequestOperationCallback, times(1)).resourceUpdated(any(IBaseResource.class), any(IBaseResource.class));
|
||||
inorder.verify(myJpaInterceptor, times(1)).resourceUpdated(any(RequestDetails.class), any(IBaseResource.class), any(IBaseResource.class));
|
||||
|
||||
// resourcePreUpdate
|
||||
assertEquals(idPart, myIds.get(0).getIdPart());
|
||||
assertEquals("1", myIds.get(0).getVersionIdPart());
|
||||
assertEquals(idPart, myIds.get(1).getIdPart());
|
||||
assertEquals(null, myIds.get(1).getVersionIdPart());
|
||||
// resourceUpdated
|
||||
assertEquals(idPart, myIds.get(2).getIdPart());
|
||||
assertEquals("1", myIds.get(2).getVersionIdPart());
|
||||
assertEquals(idPart, myIds.get(3).getIdPart());
|
||||
assertEquals("2", myIds.get(3).getVersionIdPart());
|
||||
|
||||
p = myPatientDao.read(id);
|
||||
assertEquals(true, p.getActive());
|
||||
|
||||
} finally {
|
||||
myDaoConfig.getInterceptors().remove(interceptor);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerOperationPreDelete() {
|
||||
|
||||
doAnswer(new MyOneResourceAnswer()).when(myJpaInterceptor).resourcePreDelete(any(RequestDetails.class), any(IBaseResource.class));
|
||||
doAnswer(new MyOneResourceAnswer()).when(myJpaInterceptor).resourceDeleted(any(RequestDetails.class), any(IBaseResource.class));
|
||||
|
||||
Patient p = new Patient();
|
||||
p.setActive(false);
|
||||
IIdType id = myPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||
String idPart = id.getIdPart();
|
||||
|
||||
myPatientDao.delete(id);
|
||||
|
||||
InOrder inorder = inOrder(myJpaInterceptor);
|
||||
inorder.verify(myJpaInterceptor, times(1)).resourcePreDelete(any(RequestDetails.class), any(IBaseResource.class));
|
||||
inorder.verify(myJpaInterceptor, times(1)).resourceDeleted(any(RequestDetails.class), any(IBaseResource.class));
|
||||
// resourcePreDelete
|
||||
assertEquals(idPart, myIds.get(0).getIdPart());
|
||||
assertEquals("1", myIds.get(0).getVersionIdPart());
|
||||
// resourceDeleted
|
||||
assertEquals(idPart, myIds.get(1).getIdPart());
|
||||
assertEquals("2", myIds.get(1).getVersionIdPart());
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testServerOperationUpdate() {
|
||||
|
@ -228,247 +609,28 @@ public class FhirResourceDaoR4InterceptorTest extends BaseJpaR4Test {
|
|||
verify(myServerOperationInterceptor, times(1)).resourceUpdated(Mockito.isNull(RequestDetails.class), any(IBaseResource.class), any(IBaseResource.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerOperationDelete() {
|
||||
verify(myServerOperationInterceptor, times(0)).resourceCreated(Mockito.isNull(RequestDetails.class), any(IBaseResource.class));
|
||||
verify(myServerOperationInterceptor, times(0)).resourceDeleted(Mockito.isNull(RequestDetails.class), any(IBaseResource.class));
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addName().setFamily("PATIENT");
|
||||
IIdType id = myPatientDao.create(p, (RequestDetails)null).getId();
|
||||
assertEquals(1L, id.getVersionIdPartAsLong().longValue());
|
||||
|
||||
p.addName().setFamily("2");
|
||||
myPatientDao.delete(p.getIdElement().toUnqualifiedVersionless());
|
||||
|
||||
verify(myServerOperationInterceptor, times(1)).resourceCreated(Mockito.isNull(RequestDetails.class), any(IBaseResource.class));
|
||||
verify(myServerOperationInterceptor, times(1)).resourceDeleted(Mockito.isNull(RequestDetails.class), any(IBaseResource.class));
|
||||
}
|
||||
|
||||
@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()[1];
|
||||
assertEquals("Patient/" + id + "/_history/2", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceUpdated(any(IBaseResource.class), 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)).resourceUpdated(any(IBaseResource.class), 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/1", res.getIdElement().getValue());
|
||||
res = (IBaseResource) theInvocation.getArguments()[1];
|
||||
assertEquals("Patient/" + id + "/_history/2", res.getIdElement().getValue());
|
||||
return null;
|
||||
}}).when(myRequestOperationCallback).resourceUpdated(any(IBaseResource.class), 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)).resourceUpdated(any(IBaseResource.class), any(IBaseResource.class));
|
||||
verify(myRequestOperationCallback, times(1)).resourceCreated(any(IBaseResource.class));
|
||||
verifyNoMoreInteractions(myRequestOperationCallback);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
private class MyOneResourceAnswer implements Answer {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) {
|
||||
IIdType id = ((IBaseResource) invocation.getArguments()[1]).getIdElement();
|
||||
myIds.add(new IdType(id.getValue()));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class MyTwoResourceAnswer implements Answer {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) {
|
||||
IIdType id = ((IBaseResource) invocation.getArguments()[1]).getIdElement();
|
||||
myIds.add(new IdType(id.getValue()));
|
||||
id = ((IBaseResource) invocation.getArguments()[2]).getIdElement();
|
||||
myIds.add(new IdType(id.getValue()));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,16 +20,30 @@ package ca.uhn.fhir.rest.api.server;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface IRequestOperationCallback {
|
||||
|
||||
void resourceCreated(IBaseResource theResource);
|
||||
|
||||
void resourceDeleted(IBaseResource theResource);
|
||||
|
||||
void resourcePreCreate(IBaseResource theResource);
|
||||
|
||||
void resourcePreDelete(IBaseResource theResource);
|
||||
|
||||
void resourcePreUpdate(IBaseResource theOldResource, IBaseResource theNewResource);
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated in HAPI FHIR 2.6 - Use {@link IRequestOperationCallback#resourceUpdated(IBaseResource, IBaseResource)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
void resourceUpdated(IBaseResource theResource);
|
||||
|
||||
void resourceUpdated(IBaseResource theOldResource, IBaseResource theNewResource);
|
||||
|
||||
void resourcesCreated(Collection<? extends IBaseResource> theResource);
|
||||
|
||||
void resourcesDeleted(Collection<? extends IBaseResource> theResource);
|
||||
|
@ -39,12 +53,4 @@ public interface IRequestOperationCallback {
|
|||
*/
|
||||
@Deprecated
|
||||
void resourcesUpdated(Collection<? extends IBaseResource> theResource);
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated in HAPI FHIR 2.6 - Use {@link IRequestOperationCallback#resourceUpdated(IBaseResource, IBaseResource)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
void resourceUpdated(IBaseResource theResource);
|
||||
|
||||
void resourceUpdated(IBaseResource theOldResource, IBaseResource theNewResource);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,24 @@
|
|||
package ca.uhn.fhir.rest.api.server;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.server.IRestfulServerDefaults;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Server Framework
|
||||
|
@ -26,101 +38,9 @@ import java.nio.charset.Charset;
|
|||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.server.IRestfulServerDefaults;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor;
|
||||
|
||||
public abstract class RequestDetails {
|
||||
|
||||
private class RequestOperationCallback implements IRequestOperationCallback {
|
||||
|
||||
private List<IServerInterceptor> getInterceptors() {
|
||||
if (getServer() == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return getServer().getInterceptors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourceCreated(IBaseResource theResource) {
|
||||
for (IServerInterceptor next : getInterceptors()) {
|
||||
if (next instanceof IServerOperationInterceptor) {
|
||||
((IServerOperationInterceptor) next).resourceCreated(RequestDetails.this, theResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourceDeleted(IBaseResource theResource) {
|
||||
for (IServerInterceptor next : getInterceptors()) {
|
||||
if (next instanceof IServerOperationInterceptor) {
|
||||
((IServerOperationInterceptor) next).resourceDeleted(RequestDetails.this, theResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourcesCreated(Collection<? extends IBaseResource> theResource) {
|
||||
for (IBaseResource next : theResource) {
|
||||
resourceCreated(next);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourcesDeleted(Collection<? extends IBaseResource> theResource) {
|
||||
for (IBaseResource next : theResource) {
|
||||
resourceDeleted(next);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated in HAPI FHIR 2.6 - Use {@link IRequestOperationCallback#resourceUpdated(IBaseResource, IBaseResource)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public void resourcesUpdated(Collection<? extends IBaseResource> theResource) {
|
||||
for (IBaseResource next : theResource) {
|
||||
resourceUpdated(next);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated in HAPI FHIR 2.6 - Use {@link IRequestOperationCallback#resourceUpdated(IBaseResource, IBaseResource)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void resourceUpdated(IBaseResource theResource) {
|
||||
for (IServerInterceptor next : getInterceptors()) {
|
||||
if (next instanceof IServerOperationInterceptor) {
|
||||
((IServerOperationInterceptor) next).resourceUpdated(RequestDetails.this, theResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourceUpdated(IBaseResource theOldResource, IBaseResource theNewResource) {
|
||||
for (IServerInterceptor next : getInterceptors()) {
|
||||
if (next instanceof IServerOperationInterceptor) {
|
||||
((IServerOperationInterceptor) next).resourceUpdated(RequestDetails.this, theOldResource, theNewResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private String myCompartmentName;
|
||||
private String myCompleteUrl;
|
||||
private String myFhirServerBase;
|
||||
|
@ -150,10 +70,19 @@ public abstract class RequestDetails {
|
|||
public String getCompartmentName() {
|
||||
return myCompartmentName;
|
||||
}
|
||||
|
||||
public void setCompartmentName(String theCompartmentName) {
|
||||
myCompartmentName = theCompartmentName;
|
||||
}
|
||||
|
||||
public String getCompleteUrl() {
|
||||
return myCompleteUrl;
|
||||
}
|
||||
|
||||
public void setCompleteUrl(String theCompleteUrl) {
|
||||
myCompleteUrl = theCompleteUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <b>conditional URL</b> if this request has one, or <code>null</code> otherwise. For an
|
||||
* update or delete method, this is the part of the URL after the <code>?</code>. For a create, this
|
||||
|
@ -202,6 +131,10 @@ public abstract class RequestDetails {
|
|||
return myFhirServerBase;
|
||||
}
|
||||
|
||||
public void setFhirServerBase(String theFhirServerBase) {
|
||||
myFhirServerBase = theFhirServerBase;
|
||||
}
|
||||
|
||||
public abstract String getHeader(String name);
|
||||
|
||||
public abstract List<String> getHeaders(String name);
|
||||
|
@ -210,17 +143,17 @@ public abstract class RequestDetails {
|
|||
return myId;
|
||||
}
|
||||
|
||||
public void setId(IIdType theId) {
|
||||
myId = theId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the body of the request as binary data. Either this method or {@link #getReader} may be called to read
|
||||
* the body, not both.
|
||||
*
|
||||
* @return a {@link InputStream} object containing the body of the request
|
||||
*
|
||||
* @exception IllegalStateException
|
||||
* if the {@link #getReader} method has already been called for this request
|
||||
*
|
||||
* @exception IOException
|
||||
* if an input or output exception occurred
|
||||
* @throws IllegalStateException if the {@link #getReader} method has already been called for this request
|
||||
* @throws IOException if an input or output exception occurred
|
||||
*/
|
||||
public abstract InputStream getInputStream() throws IOException;
|
||||
|
||||
|
@ -228,6 +161,10 @@ public abstract class RequestDetails {
|
|||
return myOperation;
|
||||
}
|
||||
|
||||
public void setOperation(String theOperation) {
|
||||
myOperation = theOperation;
|
||||
}
|
||||
|
||||
public Map<String, String[]> getParameters() {
|
||||
if (myParameters == null) {
|
||||
return Collections.emptyMap();
|
||||
|
@ -235,22 +172,43 @@ public abstract class RequestDetails {
|
|||
return myParameters;
|
||||
}
|
||||
|
||||
public void setParameters(Map<String, String[]> theParams) {
|
||||
myParameters = theParams;
|
||||
|
||||
for (String next : theParams.keySet()) {
|
||||
for (int i = 0; i < next.length(); i++) {
|
||||
char nextChar = next.charAt(i);
|
||||
if (nextChar == ':' || nextChar == '.') {
|
||||
if (myUnqualifiedToQualifiedNames == null) {
|
||||
myUnqualifiedToQualifiedNames = new HashMap<>();
|
||||
}
|
||||
String unqualified = next.substring(0, i);
|
||||
List<String> list = myUnqualifiedToQualifiedNames.get(unqualified);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>(4);
|
||||
myUnqualifiedToQualifiedNames.put(unqualified, list);
|
||||
}
|
||||
list.add(next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (myUnqualifiedToQualifiedNames == null) {
|
||||
myUnqualifiedToQualifiedNames = Collections.emptyMap();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the body of the request as character data using a <code>BufferedReader</code>. The reader translates the
|
||||
* character data according to the character encoding used on the body. Either this method or {@link #getInputStream}
|
||||
* may be called to read the body, not both.
|
||||
*
|
||||
* @return a <code>Reader</code> containing the body of the request
|
||||
*
|
||||
* @exception UnsupportedEncodingException
|
||||
* if the character set encoding used is not supported and the text cannot be decoded
|
||||
*
|
||||
* @exception IllegalStateException
|
||||
* if {@link #getInputStream} method has been called on this request
|
||||
*
|
||||
* @exception IOException
|
||||
* if an input or output exception occurred
|
||||
*
|
||||
* @throws UnsupportedEncodingException if the character set encoding used is not supported and the text cannot be decoded
|
||||
* @throws IllegalStateException if {@link #getInputStream} method has been called on this request
|
||||
* @throws IOException if an input or output exception occurred
|
||||
* @see javax.servlet.http.HttpServletRequest#getInputStream
|
||||
*/
|
||||
public abstract Reader getReader() throws IOException;
|
||||
|
@ -274,26 +232,51 @@ public abstract class RequestDetails {
|
|||
return myRequestPath;
|
||||
}
|
||||
|
||||
public void setRequestPath(String theRequestPath) {
|
||||
assert theRequestPath.length() == 0 || theRequestPath.charAt(0) != '/';
|
||||
myRequestPath = theRequestPath;
|
||||
}
|
||||
|
||||
public RequestTypeEnum getRequestType() {
|
||||
return myRequestType;
|
||||
}
|
||||
|
||||
public void setRequestType(RequestTypeEnum theRequestType) {
|
||||
myRequestType = theRequestType;
|
||||
}
|
||||
|
||||
public String getResourceName() {
|
||||
return myResourceName;
|
||||
}
|
||||
|
||||
public void setResourceName(String theResourceName) {
|
||||
myResourceName = theResourceName;
|
||||
}
|
||||
|
||||
public IRestfulResponse getResponse() {
|
||||
return myResponse;
|
||||
}
|
||||
|
||||
public void setResponse(IRestfulResponse theResponse) {
|
||||
this.myResponse = theResponse;
|
||||
}
|
||||
|
||||
public RestOperationTypeEnum getRestOperationType() {
|
||||
return myRestOperationType;
|
||||
}
|
||||
|
||||
public void setRestOperationType(RestOperationTypeEnum theRestOperationType) {
|
||||
myRestOperationType = theRestOperationType;
|
||||
}
|
||||
|
||||
public String getSecondaryOperation() {
|
||||
return mySecondaryOperation;
|
||||
}
|
||||
|
||||
public void setSecondaryOperation(String theSecondaryOperation) {
|
||||
mySecondaryOperation = theSecondaryOperation;
|
||||
}
|
||||
|
||||
public abstract IRestfulServerDefaults getServer();
|
||||
|
||||
/**
|
||||
|
@ -319,7 +302,7 @@ public abstract class RequestDetails {
|
|||
*/
|
||||
public Map<Object, Object> getUserData() {
|
||||
if (myUserData == null) {
|
||||
myUserData = new HashMap<Object, Object>();
|
||||
myUserData = new HashMap<>();
|
||||
}
|
||||
return myUserData;
|
||||
}
|
||||
|
@ -328,6 +311,10 @@ public abstract class RequestDetails {
|
|||
return myRespondGzip;
|
||||
}
|
||||
|
||||
public void setRespondGzip(boolean theRespondGzip) {
|
||||
myRespondGzip = theRespondGzip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this request a sub-request (i.e. a request within a batch or transaction)? This
|
||||
* flag is used internally by hapi-fhir-jpaserver-base, but not used in the plain server
|
||||
|
@ -341,90 +328,6 @@ public abstract class RequestDetails {
|
|||
return mySubRequest;
|
||||
}
|
||||
|
||||
public final byte[] loadRequestContents() {
|
||||
if (myRequestContents == null) {
|
||||
myRequestContents = getByteStreamRequestContents();
|
||||
}
|
||||
return myRequestContents;
|
||||
}
|
||||
|
||||
public void setCompartmentName(String theCompartmentName) {
|
||||
myCompartmentName = theCompartmentName;
|
||||
}
|
||||
|
||||
public void setCompleteUrl(String theCompleteUrl) {
|
||||
myCompleteUrl = theCompleteUrl;
|
||||
}
|
||||
|
||||
public void setFhirServerBase(String theFhirServerBase) {
|
||||
myFhirServerBase = theFhirServerBase;
|
||||
}
|
||||
|
||||
public void setId(IIdType theId) {
|
||||
myId = theId;
|
||||
}
|
||||
|
||||
public void setOperation(String theOperation) {
|
||||
myOperation = theOperation;
|
||||
}
|
||||
|
||||
public void setParameters(Map<String, String[]> theParams) {
|
||||
myParameters = theParams;
|
||||
|
||||
for (String next : theParams.keySet()) {
|
||||
for (int i = 0; i < next.length(); i++) {
|
||||
char nextChar = next.charAt(i);
|
||||
if (nextChar == ':' || nextChar == '.') {
|
||||
if (myUnqualifiedToQualifiedNames == null) {
|
||||
myUnqualifiedToQualifiedNames = new HashMap<String, List<String>>();
|
||||
}
|
||||
String unqualified = next.substring(0, i);
|
||||
List<String> list = myUnqualifiedToQualifiedNames.get(unqualified);
|
||||
if (list == null) {
|
||||
list = new ArrayList<String>(4);
|
||||
myUnqualifiedToQualifiedNames.put(unqualified, list);
|
||||
}
|
||||
list.add(next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (myUnqualifiedToQualifiedNames == null) {
|
||||
myUnqualifiedToQualifiedNames = Collections.emptyMap();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setRequestPath(String theRequestPath) {
|
||||
assert theRequestPath.length() == 0 || theRequestPath.charAt(0) != '/';
|
||||
myRequestPath = theRequestPath;
|
||||
}
|
||||
|
||||
public void setRequestType(RequestTypeEnum theRequestType) {
|
||||
myRequestType = theRequestType;
|
||||
}
|
||||
|
||||
public void setResourceName(String theResourceName) {
|
||||
myResourceName = theResourceName;
|
||||
}
|
||||
|
||||
public void setRespondGzip(boolean theRespondGzip) {
|
||||
myRespondGzip = theRespondGzip;
|
||||
}
|
||||
|
||||
public void setResponse(IRestfulResponse theResponse) {
|
||||
this.myResponse = theResponse;
|
||||
}
|
||||
|
||||
public void setRestOperationType(RestOperationTypeEnum theRestOperationType) {
|
||||
myRestOperationType = theRestOperationType;
|
||||
}
|
||||
|
||||
public void setSecondaryOperation(String theSecondaryOperation) {
|
||||
mySecondaryOperation = theSecondaryOperation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this request a sub-request (i.e. a request within a batch or transaction)? This
|
||||
* flag is used internally by hapi-fhir-jpaserver-base, but not used in the plain server
|
||||
|
@ -438,4 +341,113 @@ public abstract class RequestDetails {
|
|||
mySubRequest = theSubRequest;
|
||||
}
|
||||
|
||||
public final byte[] loadRequestContents() {
|
||||
if (myRequestContents == null) {
|
||||
myRequestContents = getByteStreamRequestContents();
|
||||
}
|
||||
return myRequestContents;
|
||||
}
|
||||
|
||||
private class RequestOperationCallback implements IRequestOperationCallback {
|
||||
|
||||
private List<IServerInterceptor> getInterceptors() {
|
||||
if (getServer() == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return getServer().getInterceptors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourceCreated(IBaseResource theResource) {
|
||||
for (IServerInterceptor next : getInterceptors()) {
|
||||
if (next instanceof IServerOperationInterceptor) {
|
||||
((IServerOperationInterceptor) next).resourceCreated(RequestDetails.this, theResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourceDeleted(IBaseResource theResource) {
|
||||
for (IServerInterceptor next : getInterceptors()) {
|
||||
if (next instanceof IServerOperationInterceptor) {
|
||||
((IServerOperationInterceptor) next).resourceDeleted(RequestDetails.this, theResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourcePreCreate(IBaseResource theResource) {
|
||||
for (IServerInterceptor next : getInterceptors()) {
|
||||
if (next instanceof IServerOperationInterceptor) {
|
||||
((IServerOperationInterceptor) next).resourcePreCreate(RequestDetails.this, theResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourcePreDelete(IBaseResource theResource) {
|
||||
for (IServerInterceptor next : getInterceptors()) {
|
||||
if (next instanceof IServerOperationInterceptor) {
|
||||
((IServerOperationInterceptor) next).resourcePreDelete(RequestDetails.this, theResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourcePreUpdate(IBaseResource theOldResource, IBaseResource theNewResource) {
|
||||
for (IServerInterceptor next : getInterceptors()) {
|
||||
if (next instanceof IServerOperationInterceptor) {
|
||||
((IServerOperationInterceptor) next).resourcePreUpdate(RequestDetails.this, theOldResource, theNewResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated in HAPI FHIR 2.6 - Use {@link IRequestOperationCallback#resourceUpdated(IBaseResource, IBaseResource)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void resourceUpdated(IBaseResource theResource) {
|
||||
for (IServerInterceptor next : getInterceptors()) {
|
||||
if (next instanceof IServerOperationInterceptor) {
|
||||
((IServerOperationInterceptor) next).resourceUpdated(RequestDetails.this, theResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourceUpdated(IBaseResource theOldResource, IBaseResource theNewResource) {
|
||||
for (IServerInterceptor next : getInterceptors()) {
|
||||
if (next instanceof IServerOperationInterceptor) {
|
||||
((IServerOperationInterceptor) next).resourceUpdated(RequestDetails.this, theOldResource, theNewResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourcesCreated(Collection<? extends IBaseResource> theResource) {
|
||||
for (IBaseResource next : theResource) {
|
||||
resourceCreated(next);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourcesDeleted(Collection<? extends IBaseResource> theResource) {
|
||||
for (IBaseResource next : theResource) {
|
||||
resourceDeleted(next);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated in HAPI FHIR 2.6 - Use {@link IRequestOperationCallback#resourceUpdated(IBaseResource, IBaseResource)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public void resourcesUpdated(Collection<? extends IBaseResource> theResource) {
|
||||
for (IBaseResource next : theResource) {
|
||||
resourceUpdated(next);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,9 +20,8 @@ package ca.uhn.fhir.rest.server.interceptor;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
/**
|
||||
* Server interceptor with added methods which can be called within the lifecycle of
|
||||
|
@ -34,35 +33,90 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
|
|||
public interface IServerOperationInterceptor extends IServerInterceptor {
|
||||
|
||||
/**
|
||||
* User code may call this method to indicate to an interceptor that
|
||||
* a resource is being created
|
||||
* This method is called by the server immediately after a resource has
|
||||
* been created, within the database transaction scope of the operation.
|
||||
* <p>
|
||||
* If an exception is thrown by an interceptor during this method,
|
||||
* the transaction will be rolled back.
|
||||
* </p>
|
||||
*/
|
||||
void resourceCreated(RequestDetails theRequest, IBaseResource theResource);
|
||||
|
||||
/**
|
||||
* User code may call this method to indicate to an interceptor that
|
||||
* a resource is being deleted
|
||||
* This method is called by the server immediately after a resource has
|
||||
* been deleted, within the database transaction scope of the operation.
|
||||
* <p>
|
||||
* If an exception is thrown by an interceptor during this method,
|
||||
* the transaction will be rolled back.
|
||||
* </p>
|
||||
*/
|
||||
void resourceDeleted(RequestDetails theRequest, IBaseResource theResource);
|
||||
|
||||
/**
|
||||
* User code may call this method to indicate to an interceptor that
|
||||
* a resource is being updated
|
||||
* This method is called by the server immediately before a resource is about
|
||||
* to be created, within the database transaction scope of the operation.
|
||||
* <p>
|
||||
* This method may be used to modify the resource
|
||||
* </p>
|
||||
* <p>
|
||||
* If an exception is thrown by an interceptor during this method,
|
||||
* the transaction will be rolled back.
|
||||
* </p>
|
||||
*
|
||||
* @param theResource The resource that has been provided by the client as the payload
|
||||
* to create. Interceptors may modify this
|
||||
* resource, and modifications will affect what is saved in the database.
|
||||
*/
|
||||
void resourcePreCreate(RequestDetails theRequest, IBaseResource theResource);
|
||||
|
||||
/**
|
||||
* This method is called by the server immediately before a resource is about
|
||||
* to be deleted, within the database transaction scope of the operation.
|
||||
* <p>
|
||||
* If an exception is thrown by an interceptor during this method,
|
||||
* the transaction will be rolled back.
|
||||
* </p>
|
||||
*
|
||||
* @param theResource The resource which is about to be deleted
|
||||
*/
|
||||
void resourcePreDelete(RequestDetails theRequest, IBaseResource theResource);
|
||||
|
||||
/**
|
||||
* This method is called by the server immediately before a resource is about
|
||||
* to be updated, within the database transaction scope of the operation.
|
||||
* <p>
|
||||
* This method may be used to modify the resource
|
||||
* </p>
|
||||
* <p>
|
||||
* If an exception is thrown by an interceptor during this method,
|
||||
* the transaction will be rolled back.
|
||||
* </p>
|
||||
*
|
||||
* @param theOldResource The previous version of the resource, or <code>null</code> if this is not available. Interceptors should be able to handle situations where this is null, since it is not always
|
||||
* convenient or possible to provide a value for this field, but servers should try to populate it.
|
||||
* @param theNewResource The resource that has been provided by the client as the payload
|
||||
* to update to the resource to. Interceptors may modify this
|
||||
* resource, and modifications will affect what is saved in the database.
|
||||
*/
|
||||
void resourcePreUpdate(RequestDetails theRequest, IBaseResource theOldResource, IBaseResource theNewResource);
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated in HAPI FHIR 3.0.0 in favour of {@link #resourceUpdated(RequestDetails, IBaseResource, IBaseResource)}
|
||||
*/
|
||||
@Deprecated
|
||||
void resourceUpdated(RequestDetails theRequest, IBaseResource theResource);
|
||||
|
||||
/**
|
||||
* User code may call this method to indicate to an interceptor that
|
||||
* a resource is being updated
|
||||
* This method is called by the server immediately after a resource has
|
||||
* been created, within the database transaction scope of the operation.
|
||||
* <p>
|
||||
* If an exception is thrown by an interceptor during this method,
|
||||
* the transaction will be rolled back.
|
||||
* </p>
|
||||
*
|
||||
* @param theOldResource
|
||||
* The resource as it was before the update, or <code>null</code> if this is not available. Interceptors should be able to handle situations where this is null, since it is not always
|
||||
* @param theOldResource The resource as it was before the update, or <code>null</code> if this is not available. Interceptors should be able to handle situations where this is null, since it is not always
|
||||
* convenient or possible to provide a value for this field, but servers should try to populate it.
|
||||
* @param theNewResource
|
||||
* The resource as it will be after the update
|
||||
* @param theNewResource The resource as it will be after the update
|
||||
*/
|
||||
void resourceUpdated(RequestDetails theRequest, IBaseResource theOldResource, IBaseResource theNewResource);
|
||||
|
||||
|
|
|
@ -34,6 +34,21 @@ public class ServerOperationInterceptorAdapter extends InterceptorAdapter implem
|
|||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourcePreCreate(RequestDetails theRequest, IBaseResource theResource) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourcePreDelete(RequestDetails theRequest, IBaseResource theResource) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourcePreUpdate(RequestDetails theRequest, IBaseResource theOldResource, IBaseResource theNewResource) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resourceCreated(RequestDetails theRequest, IBaseResource theResource) {
|
||||
// nothing
|
||||
|
|
|
@ -49,6 +49,19 @@
|
|||
Fix an issue in JPA server where updating a resource sometimes caused date search indexes to
|
||||
be incorrectly deleted. Thanks to Kyle Meadows for the pull request!
|
||||
</action>
|
||||
<action type="add">
|
||||
A new set of methods have been added to
|
||||
<![CDATA[<code>IServerOperationInterceptor</code>]]>
|
||||
called
|
||||
<![CDATA[<code>resourcePreCreate</code>]]>,
|
||||
<![CDATA[<code>resourcePreUpdate</code>]]>, and
|
||||
<![CDATA[<code>resourcePreDelete</code>]]>. These
|
||||
methods are called within the database transaction
|
||||
(just as the existing methods were) but are invoked
|
||||
prior to the contents being saved to the database. This
|
||||
can be useful in order to allow interceptors to
|
||||
change payload contents being saved.
|
||||
</action>
|
||||
</release>
|
||||
<release version="3.1.0" date="2017-11-23">
|
||||
<action type="add">
|
||||
|
|
Loading…
Reference in New Issue