Fix an issue in subscription interceptor which prevented the server from
starting if an invalid subscription was already in the database
This commit is contained in:
parent
17b1ff727e
commit
86a0774305
|
@ -48,6 +48,7 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.core.task.AsyncTaskExecutor;
|
||||||
import org.springframework.messaging.MessageHandler;
|
import org.springframework.messaging.MessageHandler;
|
||||||
import org.springframework.messaging.SubscribableChannel;
|
import org.springframework.messaging.SubscribableChannel;
|
||||||
import org.springframework.messaging.support.ExecutorSubscribableChannel;
|
import org.springframework.messaging.support.ExecutorSubscribableChannel;
|
||||||
|
@ -92,8 +93,10 @@ public abstract class BaseSubscriptionInterceptor<S extends IBaseResource> exten
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
@Qualifier("myEventDefinitionDaoR4")
|
@Qualifier("myEventDefinitionDaoR4")
|
||||||
private IFhirResourceDao<org.hl7.fhir.r4.model.EventDefinition> myEventDefinitionDaoR4;
|
private IFhirResourceDao<org.hl7.fhir.r4.model.EventDefinition> myEventDefinitionDaoR4;
|
||||||
@Autowired
|
@Autowired()
|
||||||
private PlatformTransactionManager myTxManager;
|
private PlatformTransactionManager myTxManager;
|
||||||
|
@Autowired
|
||||||
|
private AsyncTaskExecutor myAsyncTaskExecutor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
@ -364,6 +367,11 @@ public abstract class BaseSubscriptionInterceptor<S extends IBaseResource> exten
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public void setAsyncTaskExecutorForUnitTest(AsyncTaskExecutor theAsyncTaskExecutor) {
|
||||||
|
myAsyncTaskExecutor = theAsyncTaskExecutor;
|
||||||
|
}
|
||||||
|
|
||||||
public void setFhirContext(FhirContext theCtx) {
|
public void setFhirContext(FhirContext theCtx) {
|
||||||
myCtx = theCtx;
|
myCtx = theCtx;
|
||||||
}
|
}
|
||||||
|
@ -455,7 +463,7 @@ public abstract class BaseSubscriptionInterceptor<S extends IBaseResource> exten
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mySubscriptionActivatingSubscriber == null) {
|
if (mySubscriptionActivatingSubscriber == null) {
|
||||||
mySubscriptionActivatingSubscriber = new SubscriptionActivatingSubscriber(getSubscriptionDao(), getChannelType(), this, myTxManager);
|
mySubscriptionActivatingSubscriber = new SubscriptionActivatingSubscriber(getSubscriptionDao(), getChannelType(), this, myTxManager, myAsyncTaskExecutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerSubscriptionCheckingSubscriber();
|
registerSubscriptionCheckingSubscriber();
|
||||||
|
|
|
@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.subscription;
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -25,41 +25,51 @@ import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import ca.uhn.fhir.util.SubscriptionUtil;
|
import ca.uhn.fhir.util.SubscriptionUtil;
|
||||||
import org.apache.commons.lang3.time.DateUtils;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
import org.hl7.fhir.r4.model.Subscription;
|
import org.hl7.fhir.r4.model.Subscription;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.core.task.AsyncTaskExecutor;
|
||||||
import org.springframework.messaging.MessagingException;
|
import org.springframework.messaging.MessagingException;
|
||||||
import org.springframework.scheduling.TaskScheduler;
|
import org.springframework.scheduling.TaskScheduler;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.TransactionStatus;
|
import org.springframework.transaction.TransactionStatus;
|
||||||
import org.springframework.transaction.support.*;
|
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||||
|
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
|
||||||
|
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||||
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class SubscriptionActivatingSubscriber {
|
public class SubscriptionActivatingSubscriber {
|
||||||
|
private static boolean ourWaitForSubscriptionActivationSynchronouslyForUnitTest;
|
||||||
private final IFhirResourceDao mySubscriptionDao;
|
private final IFhirResourceDao mySubscriptionDao;
|
||||||
private final BaseSubscriptionInterceptor mySubscriptionInterceptor;
|
private final BaseSubscriptionInterceptor mySubscriptionInterceptor;
|
||||||
private final PlatformTransactionManager myTransactionManager;
|
private final PlatformTransactionManager myTransactionManager;
|
||||||
|
private final AsyncTaskExecutor myTaskExecutor;
|
||||||
private Logger ourLog = LoggerFactory.getLogger(SubscriptionActivatingSubscriber.class);
|
private Logger ourLog = LoggerFactory.getLogger(SubscriptionActivatingSubscriber.class);
|
||||||
private FhirContext myCtx;
|
private FhirContext myCtx;
|
||||||
private Subscription.SubscriptionChannelType myChannelType;
|
private Subscription.SubscriptionChannelType myChannelType;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
public SubscriptionActivatingSubscriber(IFhirResourceDao<? extends IBaseResource> theSubscriptionDao, Subscription.SubscriptionChannelType theChannelType, BaseSubscriptionInterceptor theSubscriptionInterceptor, PlatformTransactionManager theTransactionManager) {
|
public SubscriptionActivatingSubscriber(IFhirResourceDao<? extends IBaseResource> theSubscriptionDao, Subscription.SubscriptionChannelType theChannelType, BaseSubscriptionInterceptor theSubscriptionInterceptor, PlatformTransactionManager theTransactionManager, AsyncTaskExecutor theTaskExecutor) {
|
||||||
mySubscriptionDao = theSubscriptionDao;
|
mySubscriptionDao = theSubscriptionDao;
|
||||||
mySubscriptionInterceptor = theSubscriptionInterceptor;
|
mySubscriptionInterceptor = theSubscriptionInterceptor;
|
||||||
myChannelType = theChannelType;
|
myChannelType = theChannelType;
|
||||||
myCtx = theSubscriptionDao.getContext();
|
myCtx = theSubscriptionDao.getContext();
|
||||||
myTransactionManager = theTransactionManager;
|
myTransactionManager = theTransactionManager;
|
||||||
|
myTaskExecutor = theTaskExecutor;
|
||||||
|
Validate.notNull(theTaskExecutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void activateAndRegisterSubscriptionIfRequired(final IBaseResource theSubscription) {
|
public void activateAndRegisterSubscriptionIfRequired(final IBaseResource theSubscription) {
|
||||||
|
@ -75,14 +85,40 @@ public class SubscriptionActivatingSubscriber {
|
||||||
final String activeStatus = Subscription.SubscriptionStatus.ACTIVE.toCode();
|
final String activeStatus = Subscription.SubscriptionStatus.ACTIVE.toCode();
|
||||||
if (requestedStatus.equals(statusString)) {
|
if (requestedStatus.equals(statusString)) {
|
||||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||||
|
/*
|
||||||
|
* If we're in a transaction, we don't want to try and change the status from
|
||||||
|
* requested to active within the same transaction because it's too late by
|
||||||
|
* the time we get here to make modifications to the payload.
|
||||||
|
*
|
||||||
|
* So, we register a synchronization, meaning that when the transaction is
|
||||||
|
* finished, we'll schedule a task to do this in a separate worker thread
|
||||||
|
* to avoid any possibility of conflict.
|
||||||
|
*/
|
||||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
|
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void afterCommit() {
|
public void afterCommit() {
|
||||||
activateSubscription(status, activeStatus, theSubscription, requestedStatus);
|
Future<?> activationFuture = myTaskExecutor.submit(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
activateSubscription(activeStatus, theSubscription, requestedStatus);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we're running in a unit test, it's nice to be predictable in
|
||||||
|
* terms of order... In the real world it's a recipe for deadlocks
|
||||||
|
*/
|
||||||
|
if (ourWaitForSubscriptionActivationSynchronouslyForUnitTest) {
|
||||||
|
try {
|
||||||
|
activationFuture.get(5, TimeUnit.SECONDS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
ourLog.error("Failed to activate subscription", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
activateSubscription(status, activeStatus, theSubscription, requestedStatus);
|
activateSubscription(activeStatus, theSubscription, requestedStatus);
|
||||||
}
|
}
|
||||||
} else if (activeStatus.equals(statusString)) {
|
} else if (activeStatus.equals(statusString)) {
|
||||||
if (!mySubscriptionInterceptor.hasSubscription(theSubscription.getIdElement())) {
|
if (!mySubscriptionInterceptor.hasSubscription(theSubscription.getIdElement())) {
|
||||||
|
@ -97,21 +133,22 @@ public class SubscriptionActivatingSubscriber {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void activateSubscription(IPrimitiveType<?> theStatus, String theActiveStatus, final IBaseResource theSubscription, String theRequestedStatus) {
|
private void activateSubscription(String theActiveStatus, final IBaseResource theSubscription, String theRequestedStatus) {
|
||||||
theStatus.setValueAsString(theActiveStatus);
|
IBaseResource subscription = mySubscriptionDao.read(theSubscription.getIdElement());
|
||||||
ourLog.info("Activating and registering subscription {} from status {} to {}", theSubscription.getIdElement().toUnqualified().getValue(), theRequestedStatus, theActiveStatus);
|
|
||||||
|
ourLog.info("Activating and registering subscription {} from status {} to {}", subscription.getIdElement().toUnqualified().getValue(), theRequestedStatus, theActiveStatus);
|
||||||
try {
|
try {
|
||||||
mySubscriptionDao.update(theSubscription);
|
SubscriptionUtil.setStatus(myCtx, subscription, theActiveStatus);
|
||||||
|
mySubscriptionDao.update(subscription);
|
||||||
|
mySubscriptionInterceptor.registerSubscription(subscription.getIdElement(), subscription);
|
||||||
} catch (final UnprocessableEntityException e) {
|
} catch (final UnprocessableEntityException e) {
|
||||||
ourLog.info("Changing status of {} to ERROR", theSubscription.getIdElement());
|
ourLog.info("Changing status of {} to ERROR", subscription.getIdElement());
|
||||||
IBaseResource subscription = mySubscriptionDao.read(theSubscription.getIdElement());
|
|
||||||
SubscriptionUtil.setStatus(myCtx, subscription, "error");
|
SubscriptionUtil.setStatus(myCtx, subscription, "error");
|
||||||
SubscriptionUtil.setReason(myCtx, subscription, e.getMessage());
|
SubscriptionUtil.setReason(myCtx, subscription, e.getMessage());
|
||||||
mySubscriptionDao.update(subscription);
|
mySubscriptionDao.update(subscription);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void handleMessage(RestOperationTypeEnum theOperationType, IIdType theId, final IBaseResource theSubscription) throws MessagingException {
|
public void handleMessage(RestOperationTypeEnum theOperationType, IIdType theId, final IBaseResource theSubscription) throws MessagingException {
|
||||||
|
|
||||||
switch (theOperationType) {
|
switch (theOperationType) {
|
||||||
|
@ -137,4 +174,9 @@ public class SubscriptionActivatingSubscriber {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public static void setWaitForSubscriptionActivationSynchronouslyForUnitTest(boolean theWaitForSubscriptionActivationSynchronouslyForUnitTest) {
|
||||||
|
ourWaitForSubscriptionActivationSynchronouslyForUnitTest = theWaitForSubscriptionActivationSynchronouslyForUnitTest;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ public class SubscriptionsRequireManualActivationInterceptorDstu2 extends Server
|
||||||
|
|
||||||
if (newStatus == null) {
|
if (newStatus == null) {
|
||||||
String actualCode = subscription.getStatusElement().getValueAsString();
|
String actualCode = subscription.getStatusElement().getValueAsString();
|
||||||
throw new UnprocessableEntityException("Can not " + theOperation.getCode() + " resource: Subscription.status must be populated" + ((isNotBlank(actualCode)) ? " (invalid value " + actualCode + ")" : ""));
|
throw new UnprocessableEntityException("Can not " + theOperation.getCode() + " resource: Subscription.status must be populated on this server" + ((isNotBlank(actualCode)) ? " (invalid value " + actualCode + ")" : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theOldResourceOrNull != null) {
|
if (theOldResourceOrNull != null) {
|
||||||
|
@ -108,7 +108,7 @@ public class SubscriptionsRequireManualActivationInterceptorDstu2 extends Server
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theSubscription.getStatus() == null) {
|
if (theSubscription.getStatus() == null) {
|
||||||
throw new UnprocessableEntityException("Can not " + theOperation.getCode().toLowerCase() + " resource: Subscription.status must be populated");
|
throw new UnprocessableEntityException("Can not " + theOperation.getCode().toLowerCase() + " resource: Subscription.status must be populated on this server");
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnprocessableEntityException("Subscription.status must be '" + SubscriptionStatusEnum.OFF.getCode() + "' or '" + SubscriptionStatusEnum.REQUESTED.getCode() + "' on a newly created subscription");
|
throw new UnprocessableEntityException("Subscription.status must be '" + SubscriptionStatusEnum.OFF.getCode() + "' or '" + SubscriptionStatusEnum.REQUESTED.getCode() + "' on a newly created subscription");
|
||||||
|
|
|
@ -74,7 +74,7 @@ public class SubscriptionsRequireManualActivationInterceptorDstu3 extends Server
|
||||||
|
|
||||||
if (newStatus == null) {
|
if (newStatus == null) {
|
||||||
String actualCode = subscription.getStatusElement().getValueAsString();
|
String actualCode = subscription.getStatusElement().getValueAsString();
|
||||||
throw new UnprocessableEntityException("Can not " + theOperation.getCode() + " resource: Subscription.status must be populated" + ((isNotBlank(actualCode)) ? " (invalid value " + actualCode + ")" : ""));
|
throw new UnprocessableEntityException("Can not " + theOperation.getCode() + " resource: Subscription.status must be populated on this server" + ((isNotBlank(actualCode)) ? " (invalid value " + actualCode + ")" : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theOldResourceOrNull != null) {
|
if (theOldResourceOrNull != null) {
|
||||||
|
@ -108,7 +108,7 @@ public class SubscriptionsRequireManualActivationInterceptorDstu3 extends Server
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theSubscription.getStatus() == null) {
|
if (theSubscription.getStatus() == null) {
|
||||||
throw new UnprocessableEntityException("Can not " + theOperation.getCode().toLowerCase() + " resource: Subscription.status must be populated");
|
throw new UnprocessableEntityException("Can not " + theOperation.getCode().toLowerCase() + " resource: Subscription.status must be populated on this server");
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnprocessableEntityException("Subscription.status must be '" + SubscriptionStatus.OFF.toCode() + "' or '" + SubscriptionStatus.REQUESTED.toCode() + "' on a newly created subscription");
|
throw new UnprocessableEntityException("Subscription.status must be '" + SubscriptionStatus.OFF.toCode() + "' or '" + SubscriptionStatus.REQUESTED.toCode() + "' on a newly created subscription");
|
||||||
|
|
|
@ -74,7 +74,7 @@ public class SubscriptionsRequireManualActivationInterceptorR4 extends ServerOpe
|
||||||
|
|
||||||
if (newStatus == null) {
|
if (newStatus == null) {
|
||||||
String actualCode = subscription.getStatusElement().getValueAsString();
|
String actualCode = subscription.getStatusElement().getValueAsString();
|
||||||
throw new UnprocessableEntityException("Can not " + theOperation.getCode() + " resource: Subscription.status must be populated" + ((isNotBlank(actualCode)) ? " (invalid value " + actualCode + ")" : ""));
|
throw new UnprocessableEntityException("Can not " + theOperation.getCode() + " resource: Subscription.status must be populated on this server" + ((isNotBlank(actualCode)) ? " (invalid value " + actualCode + ")" : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theOldResourceOrNull != null) {
|
if (theOldResourceOrNull != null) {
|
||||||
|
@ -108,7 +108,7 @@ public class SubscriptionsRequireManualActivationInterceptorR4 extends ServerOpe
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theSubscription.getStatus() == null) {
|
if (theSubscription.getStatus() == null) {
|
||||||
throw new UnprocessableEntityException("Can not " + theOperation.getCode().toLowerCase() + " resource: Subscription.status must be populated");
|
throw new UnprocessableEntityException("Can not " + theOperation.getCode().toLowerCase() + " resource: Subscription.status must be populated on this server");
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnprocessableEntityException("Subscription.status must be '" + SubscriptionStatus.OFF.toCode() + "' or '" + SubscriptionStatus.REQUESTED.toCode() + "' on a newly created subscription");
|
throw new UnprocessableEntityException("Subscription.status must be '" + SubscriptionStatus.OFF.toCode() + "' or '" + SubscriptionStatus.REQUESTED.toCode() + "' on a newly created subscription");
|
||||||
|
|
|
@ -47,7 +47,7 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Connection getConnection() throws SQLException {
|
public Connection getConnection() {
|
||||||
ConnectionWrapper retVal;
|
ConnectionWrapper retVal;
|
||||||
try {
|
try {
|
||||||
retVal = new ConnectionWrapper(super.getConnection());
|
retVal = new ConnectionWrapper(super.getConnection());
|
||||||
|
|
|
@ -1,21 +1,35 @@
|
||||||
package ca.uhn.fhir.jpa.dao.dstu3;
|
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||||
|
|
||||||
import static org.junit.Assert.fail;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import static org.mockito.Mockito.mock;
|
import ca.uhn.fhir.jpa.config.TestDstu3Config;
|
||||||
|
import ca.uhn.fhir.jpa.dao.*;
|
||||||
import java.io.IOException;
|
import ca.uhn.fhir.jpa.dao.data.*;
|
||||||
import java.io.InputStream;
|
import ca.uhn.fhir.jpa.dao.dstu2.FhirResourceDaoDstu2SearchNoFtTest;
|
||||||
import java.util.Map;
|
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
|
||||||
|
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||||
import javax.persistence.EntityManager;
|
import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3;
|
||||||
|
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
|
||||||
|
import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
|
||||||
|
import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc;
|
||||||
|
import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc;
|
||||||
|
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||||
|
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainDstu3;
|
||||||
|
import ca.uhn.fhir.parser.IParser;
|
||||||
|
import ca.uhn.fhir.parser.StrictErrorHandler;
|
||||||
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
|
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
import ca.uhn.fhir.util.UrlUtil;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.hibernate.search.jpa.FullTextEntityManager;
|
import org.hibernate.search.jpa.FullTextEntityManager;
|
||||||
import org.hibernate.search.jpa.Search;
|
import org.hibernate.search.jpa.Search;
|
||||||
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
|
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
|
||||||
import org.hl7.fhir.dstu3.model.*;
|
import org.hl7.fhir.dstu3.model.*;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.junit.*;
|
import org.junit.After;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
@ -27,29 +41,16 @@ import org.springframework.transaction.TransactionDefinition;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import javax.persistence.EntityManager;
|
||||||
import ca.uhn.fhir.jpa.config.TestDstu3Config;
|
import java.io.IOException;
|
||||||
import ca.uhn.fhir.jpa.dao.*;
|
import java.io.InputStream;
|
||||||
import ca.uhn.fhir.jpa.dao.data.*;
|
import java.util.Map;
|
||||||
import ca.uhn.fhir.jpa.dao.dstu2.FhirResourceDaoDstu2SearchNoFtTest;
|
|
||||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
|
import static org.junit.Assert.*;
|
||||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
import static org.mockito.Mockito.mock;
|
||||||
import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3;
|
|
||||||
import ca.uhn.fhir.jpa.search.*;
|
|
||||||
import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc;
|
|
||||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
|
||||||
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainDstu3;
|
|
||||||
import ca.uhn.fhir.parser.IParser;
|
|
||||||
import ca.uhn.fhir.parser.StrictErrorHandler;
|
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
|
||||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
|
||||||
import ca.uhn.fhir.rest.server.method.MethodUtil;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
|
||||||
import ca.uhn.fhir.util.UrlUtil;
|
|
||||||
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ContextConfiguration(classes= {TestDstu3Config.class})
|
@ContextConfiguration(classes = {TestDstu3Config.class})
|
||||||
public abstract class BaseJpaDstu3Test extends BaseJpaTest {
|
public abstract class BaseJpaDstu3Test extends BaseJpaTest {
|
||||||
|
|
||||||
private static JpaValidationSupportChainDstu3 ourJpaValidationSupportChainDstu3;
|
private static JpaValidationSupportChainDstu3 ourJpaValidationSupportChainDstu3;
|
||||||
|
@ -254,6 +255,7 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
|
||||||
@Before
|
@Before
|
||||||
@Transactional()
|
@Transactional()
|
||||||
public void beforePurgeDatabase() {
|
public void beforePurgeDatabase() {
|
||||||
|
|
||||||
final EntityManager entityManager = this.myEntityManager;
|
final EntityManager entityManager = this.myEntityManager;
|
||||||
purgeDatabase(entityManager, myTxManager, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegsitry);
|
purgeDatabase(entityManager, myTxManager, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegsitry);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.dao.dstu3;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
|
import ca.uhn.fhir.jpa.subscription.SubscriptionActivatingSubscriber;
|
||||||
import ca.uhn.fhir.jpa.subscription.resthook.SubscriptionRestHookInterceptor;
|
import ca.uhn.fhir.jpa.subscription.resthook.SubscriptionRestHookInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
@ -9,6 +10,7 @@ import org.hl7.fhir.dstu3.model.Subscription;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.transaction.TransactionStatus;
|
import org.springframework.transaction.TransactionStatus;
|
||||||
|
@ -26,10 +28,16 @@ public class FhirResourceDaoDstu3InvalidSubscriptionTest extends BaseJpaDstu3Tes
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void afterResetDao() {
|
public void afterResetDao() {
|
||||||
|
SubscriptionActivatingSubscriber.setWaitForSubscriptionActivationSynchronouslyForUnitTest(false);
|
||||||
myDaoConfig.setResourceServerIdStrategy(new DaoConfig().getResourceServerIdStrategy());
|
myDaoConfig.setResourceServerIdStrategy(new DaoConfig().getResourceServerIdStrategy());
|
||||||
BaseHapiFhirDao.setValidationDisabledForUnitTest(false);
|
BaseHapiFhirDao.setValidationDisabledForUnitTest(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() {
|
||||||
|
SubscriptionActivatingSubscriber.setWaitForSubscriptionActivationSynchronouslyForUnitTest(true);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateInvalidSubscriptionOkButCanNotActivate() {
|
public void testCreateInvalidSubscriptionOkButCanNotActivate() {
|
||||||
Subscription s = new Subscription();
|
Subscription s = new Subscription();
|
||||||
|
@ -45,7 +53,7 @@ public class FhirResourceDaoDstu3InvalidSubscriptionTest extends BaseJpaDstu3Tes
|
||||||
mySubscriptionDao.update(s);
|
mySubscriptionDao.update(s);
|
||||||
fail();
|
fail();
|
||||||
} catch (UnprocessableEntityException e) {
|
} catch (UnprocessableEntityException e) {
|
||||||
assertEquals("Subscription.criteria must be in the form \"{Resource Type}?[params]", e.getMessage());
|
assertEquals("Subscription.criteria must be in the form \"{Resource Type}?[params]\"", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
|
import ca.uhn.fhir.jpa.subscription.SubscriptionActivatingSubscriber;
|
||||||
import ca.uhn.fhir.jpa.subscription.resthook.SubscriptionRestHookInterceptor;
|
import ca.uhn.fhir.jpa.subscription.resthook.SubscriptionRestHookInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
@ -9,6 +10,7 @@ import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.r4.model.Subscription;
|
import org.hl7.fhir.r4.model.Subscription;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.transaction.TransactionStatus;
|
import org.springframework.transaction.TransactionStatus;
|
||||||
|
@ -26,10 +28,16 @@ public class FhirResourceDaoR4InvalidSubscriptionTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void afterResetDao() {
|
public void afterResetDao() {
|
||||||
|
SubscriptionActivatingSubscriber.setWaitForSubscriptionActivationSynchronouslyForUnitTest(false);
|
||||||
myDaoConfig.setResourceServerIdStrategy(new DaoConfig().getResourceServerIdStrategy());
|
myDaoConfig.setResourceServerIdStrategy(new DaoConfig().getResourceServerIdStrategy());
|
||||||
BaseHapiFhirDao.setValidationDisabledForUnitTest(false);
|
BaseHapiFhirDao.setValidationDisabledForUnitTest(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() {
|
||||||
|
SubscriptionActivatingSubscriber.setWaitForSubscriptionActivationSynchronouslyForUnitTest(true);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateInvalidSubscriptionOkButCanNotActivate() {
|
public void testCreateInvalidSubscriptionOkButCanNotActivate() {
|
||||||
Subscription s = new Subscription();
|
Subscription s = new Subscription();
|
||||||
|
@ -45,7 +53,7 @@ public class FhirResourceDaoR4InvalidSubscriptionTest extends BaseJpaR4Test {
|
||||||
mySubscriptionDao.update(s);
|
mySubscriptionDao.update(s);
|
||||||
fail();
|
fail();
|
||||||
} catch (UnprocessableEntityException e) {
|
} catch (UnprocessableEntityException e) {
|
||||||
assertEquals("Subscription.criteria must be in the form \"{Resource Type}?[params]", e.getMessage());
|
assertEquals("Subscription.criteria must be in the form \"{Resource Type}?[params]\"", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package ca.uhn.fhir.jpa.dao.r4;
|
package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
||||||
import ca.uhn.fhir.jpa.entity.Search;
|
import ca.uhn.fhir.jpa.entity.Search;
|
||||||
|
@ -45,11 +46,13 @@ public class FhirResourceDaoR4SearchPageExpiryTest extends BaseJpaR4Test {
|
||||||
public void before() {
|
public void before() {
|
||||||
StaleSearchDeletingSvcImpl staleSearchDeletingSvc = AopTestUtils.getTargetObject(myStaleSearchDeletingSvc);
|
StaleSearchDeletingSvcImpl staleSearchDeletingSvc = AopTestUtils.getTargetObject(myStaleSearchDeletingSvc);
|
||||||
staleSearchDeletingSvc.setCutoffSlackForUnitTest(0);
|
staleSearchDeletingSvc.setCutoffSlackForUnitTest(0);
|
||||||
|
myDaoConfig.setCountSearchResultsUpTo(new DaoConfig().getCountSearchResultsUpTo());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void beforeDisableResultReuse() {
|
public void beforeDisableResultReuse() {
|
||||||
myDaoConfig.setReuseCachedSearchResultsForMillis(null);
|
myDaoConfig.setReuseCachedSearchResultsForMillis(null);
|
||||||
|
myDaoConfig.setCountSearchResultsUpTo(10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.junit.*;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.core.task.AsyncTaskExecutor;
|
||||||
|
|
||||||
import javax.mail.internet.InternetAddress;
|
import javax.mail.internet.InternetAddress;
|
||||||
import javax.mail.internet.MimeMessage;
|
import javax.mail.internet.MimeMessage;
|
||||||
|
@ -42,6 +43,8 @@ public class EmailSubscriptionDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private List<IFhirResourceDao<?>> myResourceDaos;
|
private List<IFhirResourceDao<?>> myResourceDaos;
|
||||||
|
@Autowired
|
||||||
|
private AsyncTaskExecutor myAsyncTaskExecutor;
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void after() throws Exception {
|
public void after() throws Exception {
|
||||||
|
@ -70,6 +73,7 @@ public class EmailSubscriptionDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
mySubscriber.setResourceDaos(myResourceDaos);
|
mySubscriber.setResourceDaos(myResourceDaos);
|
||||||
mySubscriber.setFhirContext(myFhirCtx);
|
mySubscriber.setFhirContext(myFhirCtx);
|
||||||
mySubscriber.setTxManager(ourTxManager);
|
mySubscriber.setTxManager(ourTxManager);
|
||||||
|
mySubscriber.setAsyncTaskExecutorForUnitTest(myAsyncTaskExecutor);
|
||||||
mySubscriber.start();
|
mySubscriber.start();
|
||||||
ourRestServer.registerInterceptor(mySubscriber);
|
ourRestServer.registerInterceptor(mySubscriber);
|
||||||
|
|
||||||
|
|
|
@ -1,35 +1,21 @@
|
||||||
|
|
||||||
package ca.uhn.fhir.jpa.subscription.email;
|
package ca.uhn.fhir.jpa.subscription.email;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
|
||||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.provider.dstu3.BaseResourceProviderDstu3Test;
|
import ca.uhn.fhir.jpa.provider.dstu3.BaseResourceProviderDstu3Test;
|
||||||
import ca.uhn.fhir.jpa.subscription.RestHookTestDstu2Test;
|
import ca.uhn.fhir.jpa.subscription.RestHookTestDstu2Test;
|
||||||
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
||||||
import ca.uhn.fhir.jpa.util.JpaConstants;
|
import ca.uhn.fhir.jpa.util.JpaConstants;
|
||||||
import ca.uhn.fhir.rest.annotation.Create;
|
|
||||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Update;
|
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
|
||||||
import ca.uhn.fhir.util.PortUtil;
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.icegreen.greenmail.store.FolderException;
|
import com.icegreen.greenmail.store.FolderException;
|
||||||
import com.icegreen.greenmail.util.GreenMail;
|
import com.icegreen.greenmail.util.GreenMail;
|
||||||
import com.icegreen.greenmail.util.ServerSetup;
|
import com.icegreen.greenmail.util.ServerSetup;
|
||||||
import org.eclipse.jetty.server.Server;
|
|
||||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
|
||||||
import org.hl7.fhir.dstu3.model.*;
|
import org.hl7.fhir.dstu3.model.*;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import javax.mail.internet.InternetAddress;
|
import javax.mail.internet.InternetAddress;
|
||||||
import javax.mail.internet.MimeMessage;
|
import javax.mail.internet.MimeMessage;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -53,7 +39,7 @@ public class EmailSubscriptionDstu3Test extends BaseResourceProviderDstu3Test {
|
||||||
public void afterUnregisterEmailListener() {
|
public void afterUnregisterEmailListener() {
|
||||||
ourLog.info("**** Starting @After *****");
|
ourLog.info("**** Starting @After *****");
|
||||||
|
|
||||||
for (IIdType next : mySubscriptionIds){
|
for (IIdType next : mySubscriptionIds) {
|
||||||
ourClient.delete().resourceById(next).execute();
|
ourClient.delete().resourceById(next).execute();
|
||||||
}
|
}
|
||||||
mySubscriptionIds.clear();
|
mySubscriptionIds.clear();
|
||||||
|
@ -71,7 +57,8 @@ public class EmailSubscriptionDstu3Test extends BaseResourceProviderDstu3Test {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void beforeRegisterEmailListener() throws FolderException {
|
public void beforeRegisterEmailListener() throws FolderException {
|
||||||
ourTestSmtp.purgeEmailFromAllMailboxes();;
|
ourTestSmtp.purgeEmailFromAllMailboxes();
|
||||||
|
;
|
||||||
ourRestServer.registerInterceptor(ourEmailSubscriptionInterceptor);
|
ourRestServer.registerInterceptor(ourEmailSubscriptionInterceptor);
|
||||||
|
|
||||||
JavaMailEmailSender emailSender = new JavaMailEmailSender();
|
JavaMailEmailSender emailSender = new JavaMailEmailSender();
|
||||||
|
@ -83,24 +70,6 @@ public class EmailSubscriptionDstu3Test extends BaseResourceProviderDstu3Test {
|
||||||
ourEmailSubscriptionInterceptor.setDefaultFromAddress("123@hapifhir.io");
|
ourEmailSubscriptionInterceptor.setDefaultFromAddress("123@hapifhir.io");
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void afterClass() {
|
|
||||||
ourTestSmtp.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
public static void beforeClass() {
|
|
||||||
ourListenerPort = RandomServerPortProvider.findFreePort();
|
|
||||||
ServerSetup smtp = new ServerSetup(ourListenerPort, null, ServerSetup.PROTOCOL_SMTP);
|
|
||||||
smtp.setServerStartupTimeout(2000);
|
|
||||||
smtp.setReadTimeout(2000);
|
|
||||||
smtp.setConnectionTimeout(2000);
|
|
||||||
ourTestSmtp = new GreenMail(smtp);
|
|
||||||
ourTestSmtp.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private Subscription createSubscription(String theCriteria, String thePayload) throws InterruptedException {
|
private Subscription createSubscription(String theCriteria, String thePayload) throws InterruptedException {
|
||||||
Subscription subscription = new Subscription();
|
Subscription subscription = new Subscription();
|
||||||
subscription.setReason("Monitor new neonatal function (note, age will be determined by the monitor)");
|
subscription.setReason("Monitor new neonatal function (note, age will be determined by the monitor)");
|
||||||
|
@ -161,15 +130,14 @@ public class EmailSubscriptionDstu3Test extends BaseResourceProviderDstu3Test {
|
||||||
|
|
||||||
List<MimeMessage> received = Arrays.asList(ourTestSmtp.getReceivedMessages());
|
List<MimeMessage> received = Arrays.asList(ourTestSmtp.getReceivedMessages());
|
||||||
assertEquals(1, received.get(0).getFrom().length);
|
assertEquals(1, received.get(0).getFrom().length);
|
||||||
assertEquals("123@hapifhir.io", ((InternetAddress)received.get(0).getFrom()[0]).getAddress());
|
assertEquals("123@hapifhir.io", ((InternetAddress) received.get(0).getFrom()[0]).getAddress());
|
||||||
assertEquals(1, received.get(0).getAllRecipients().length);
|
assertEquals(1, received.get(0).getAllRecipients().length);
|
||||||
assertEquals("foo@example.com", ((InternetAddress)received.get(0).getAllRecipients()[0]).getAddress());
|
assertEquals("foo@example.com", ((InternetAddress) received.get(0).getAllRecipients()[0]).getAddress());
|
||||||
assertEquals("text/plain; charset=us-ascii", received.get(0).getContentType());
|
assertEquals("text/plain; charset=us-ascii", received.get(0).getContentType());
|
||||||
assertEquals("This is the body", received.get(0).getContent().toString().trim());
|
assertEquals("This is the body", received.get(0).getContent().toString().trim());
|
||||||
assertEquals(mySubscriptionIds.get(0).toUnqualifiedVersionless().getValue(), received.get(0).getHeader("X-FHIR-Subscription")[0]);
|
assertEquals(mySubscriptionIds.get(0).toUnqualifiedVersionless().getValue(), received.get(0).getHeader("X-FHIR-Subscription")[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEmailSubscriptionWithCustom() throws Exception {
|
public void testEmailSubscriptionWithCustom() throws Exception {
|
||||||
String payload = "This is the body";
|
String payload = "This is the body";
|
||||||
|
@ -180,6 +148,7 @@ public class EmailSubscriptionDstu3Test extends BaseResourceProviderDstu3Test {
|
||||||
|
|
||||||
Subscription subscriptionTemp = ourClient.read(Subscription.class, sub1.getId());
|
Subscription subscriptionTemp = ourClient.read(Subscription.class, sub1.getId());
|
||||||
Assert.assertNotNull(subscriptionTemp);
|
Assert.assertNotNull(subscriptionTemp);
|
||||||
|
|
||||||
subscriptionTemp.getChannel().addExtension()
|
subscriptionTemp.getChannel().addExtension()
|
||||||
.setUrl(JpaConstants.EXT_SUBSCRIPTION_EMAIL_FROM)
|
.setUrl(JpaConstants.EXT_SUBSCRIPTION_EMAIL_FROM)
|
||||||
.setValue(new StringType("mailto:myfrom@from.com"));
|
.setValue(new StringType("mailto:myfrom@from.com"));
|
||||||
|
@ -208,9 +177,9 @@ public class EmailSubscriptionDstu3Test extends BaseResourceProviderDstu3Test {
|
||||||
List<MimeMessage> received = Arrays.asList(ourTestSmtp.getReceivedMessages());
|
List<MimeMessage> received = Arrays.asList(ourTestSmtp.getReceivedMessages());
|
||||||
assertEquals(1, received.size());
|
assertEquals(1, received.size());
|
||||||
assertEquals(1, received.get(0).getFrom().length);
|
assertEquals(1, received.get(0).getFrom().length);
|
||||||
assertEquals("myfrom@from.com", ((InternetAddress)received.get(0).getFrom()[0]).getAddress());
|
assertEquals("myfrom@from.com", ((InternetAddress) received.get(0).getFrom()[0]).getAddress());
|
||||||
assertEquals(1, received.get(0).getAllRecipients().length);
|
assertEquals(1, received.get(0).getAllRecipients().length);
|
||||||
assertEquals("foo@example.com", ((InternetAddress)received.get(0).getAllRecipients()[0]).getAddress());
|
assertEquals("foo@example.com", ((InternetAddress) received.get(0).getAllRecipients()[0]).getAddress());
|
||||||
assertEquals("text/plain; charset=us-ascii", received.get(0).getContentType());
|
assertEquals("text/plain; charset=us-ascii", received.get(0).getContentType());
|
||||||
assertEquals("This is a subject", received.get(0).getSubject().toString().trim());
|
assertEquals("This is a subject", received.get(0).getSubject().toString().trim());
|
||||||
assertEquals("This is the body", received.get(0).getContent().toString().trim());
|
assertEquals("This is the body", received.get(0).getContent().toString().trim());
|
||||||
|
@ -235,14 +204,11 @@ public class EmailSubscriptionDstu3Test extends BaseResourceProviderDstu3Test {
|
||||||
.setValue(new StringType("This is a subject"));
|
.setValue(new StringType("This is a subject"));
|
||||||
subscriptionTemp.setIdElement(subscriptionTemp.getIdElement().toUnqualifiedVersionless());
|
subscriptionTemp.setIdElement(subscriptionTemp.getIdElement().toUnqualifiedVersionless());
|
||||||
|
|
||||||
|
IIdType id = ourClient.update().resource(subscriptionTemp).withId(subscriptionTemp.getIdElement()).execute().getId();
|
||||||
|
ourLog.info("Subscription ID is: {}", id.getValue());
|
||||||
|
|
||||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(subscriptionTemp));
|
|
||||||
|
|
||||||
|
|
||||||
ourClient.update().resource(subscriptionTemp).withId(subscriptionTemp.getIdElement()).execute();
|
|
||||||
waitForQueueToDrain();
|
waitForQueueToDrain();
|
||||||
|
|
||||||
|
|
||||||
sendObservation(code, "SNOMED-CT");
|
sendObservation(code, "SNOMED-CT");
|
||||||
waitForQueueToDrain();
|
waitForQueueToDrain();
|
||||||
|
|
||||||
|
@ -256,17 +222,39 @@ public class EmailSubscriptionDstu3Test extends BaseResourceProviderDstu3Test {
|
||||||
List<MimeMessage> received = Arrays.asList(ourTestSmtp.getReceivedMessages());
|
List<MimeMessage> received = Arrays.asList(ourTestSmtp.getReceivedMessages());
|
||||||
assertEquals(1, received.size());
|
assertEquals(1, received.size());
|
||||||
assertEquals(1, received.get(0).getFrom().length);
|
assertEquals(1, received.get(0).getFrom().length);
|
||||||
assertEquals("myfrom@from.com", ((InternetAddress)received.get(0).getFrom()[0]).getAddress());
|
assertEquals("myfrom@from.com", ((InternetAddress) received.get(0).getFrom()[0]).getAddress());
|
||||||
assertEquals(1, received.get(0).getAllRecipients().length);
|
assertEquals(1, received.get(0).getAllRecipients().length);
|
||||||
assertEquals("foo@example.com", ((InternetAddress)received.get(0).getAllRecipients()[0]).getAddress());
|
assertEquals("foo@example.com", ((InternetAddress) received.get(0).getAllRecipients()[0]).getAddress());
|
||||||
assertEquals("text/plain; charset=us-ascii", received.get(0).getContentType());
|
assertEquals("text/plain; charset=us-ascii", received.get(0).getContentType());
|
||||||
assertEquals("This is a subject", received.get(0).getSubject().toString().trim());
|
assertEquals("This is a subject", received.get(0).getSubject().toString().trim());
|
||||||
assertEquals("This is the body", received.get(0).getContent().toString().trim());
|
assertEquals("This is the body", received.get(0).getContent().toString().trim());
|
||||||
assertEquals(mySubscriptionIds.get(0).toUnqualifiedVersionless().getValue(), received.get(0).getHeader("X-FHIR-Subscription")[0]);
|
assertEquals(mySubscriptionIds.get(0).toUnqualifiedVersionless().getValue(), received.get(0).getHeader("X-FHIR-Subscription")[0]);
|
||||||
|
|
||||||
|
ourLog.info("Subscription: {}", myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(ourClient.history().onInstance(id).andReturnBundle(Bundle.class).execute()));
|
||||||
|
|
||||||
|
Subscription subscription = ourClient.read().resource(Subscription.class).withId(id.toUnqualifiedVersionless()).execute();
|
||||||
|
assertEquals(Subscription.SubscriptionStatus.ACTIVE, subscription.getStatus());
|
||||||
|
assertEquals("3", subscription.getIdElement().getVersionIdPart());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void waitForQueueToDrain() throws InterruptedException {
|
private void waitForQueueToDrain() throws InterruptedException {
|
||||||
RestHookTestDstu2Test.waitForQueueToDrain(ourEmailSubscriptionInterceptor);
|
RestHookTestDstu2Test.waitForQueueToDrain(ourEmailSubscriptionInterceptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClass() {
|
||||||
|
ourTestSmtp.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void beforeClass() {
|
||||||
|
ourListenerPort = RandomServerPortProvider.findFreePort();
|
||||||
|
ServerSetup smtp = new ServerSetup(ourListenerPort, null, ServerSetup.PROTOCOL_SMTP);
|
||||||
|
smtp.setServerStartupTimeout(2000);
|
||||||
|
smtp.setReadTimeout(2000);
|
||||||
|
smtp.setConnectionTimeout(2000);
|
||||||
|
ourTestSmtp = new GreenMail(smtp);
|
||||||
|
ourTestSmtp.start();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.subscription.r4;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jpa.provider.r4.BaseResourceProviderR4Test;
|
import ca.uhn.fhir.jpa.provider.r4.BaseResourceProviderR4Test;
|
||||||
import ca.uhn.fhir.jpa.subscription.RestHookTestDstu2Test;
|
import ca.uhn.fhir.jpa.subscription.RestHookTestDstu2Test;
|
||||||
|
import ca.uhn.fhir.jpa.subscription.SubscriptionActivatingSubscriber;
|
||||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||||
import ca.uhn.fhir.rest.annotation.Update;
|
import ca.uhn.fhir.rest.annotation.Update;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
|
@ -38,11 +39,22 @@ public class RestHookActivatesPreExistingSubscriptionsR4Test extends BaseResourc
|
||||||
private static List<String> ourContentTypes = new ArrayList<>();
|
private static List<String> ourContentTypes = new ArrayList<>();
|
||||||
private static List<String> ourHeaders = new ArrayList<>();
|
private static List<String> ourHeaders = new ArrayList<>();
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void afterResetSubscriptionActivatingInterceptor() {
|
||||||
|
SubscriptionActivatingSubscriber.setWaitForSubscriptionActivationSynchronouslyForUnitTest(false);
|
||||||
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void afterUnregisterRestHookListener() {
|
public void afterUnregisterRestHookListener() {
|
||||||
ourRestServer.unregisterInterceptor(getRestHookSubscriptionInterceptor());
|
ourRestServer.unregisterInterceptor(getRestHookSubscriptionInterceptor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void beforeSetSubscriptionActivatingInterceptor() {
|
||||||
|
SubscriptionActivatingSubscriber.setWaitForSubscriptionActivationSynchronouslyForUnitTest(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private Subscription createSubscription(String theCriteria, String thePayload, String theEndpoint) throws InterruptedException {
|
private Subscription createSubscription(String theCriteria, String thePayload, String theEndpoint) throws InterruptedException {
|
||||||
Subscription subscription = new Subscription();
|
Subscription subscription = new Subscription();
|
||||||
subscription.setReason("Monitor new neonatal function (note, age will be determined by the monitor)");
|
subscription.setReason("Monitor new neonatal function (note, age will be determined by the monitor)");
|
||||||
|
|
|
@ -9,9 +9,9 @@ package ca.uhn.fhir.spring.boot.autoconfigure;
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -21,11 +21,6 @@ package ca.uhn.fhir.spring.boot.autoconfigure;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsProvider;
|
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsProvider;
|
||||||
import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu2;
|
import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu2;
|
||||||
|
@ -47,16 +42,10 @@ import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import org.apache.http.client.HttpClient;
|
import org.apache.http.client.HttpClient;
|
||||||
|
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
import org.springframework.boot.autoconfigure.condition.*;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ResourceCondition;
|
|
||||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
||||||
|
@ -67,242 +56,269 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Conditional;
|
import org.springframework.context.annotation.Conditional;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||||
|
import org.springframework.core.task.AsyncTaskExecutor;
|
||||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||||
|
import org.springframework.scheduling.TaskScheduler;
|
||||||
|
import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler;
|
||||||
|
import org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link EnableAutoConfiguration Auto-configuration} for HAPI FHIR.
|
* {@link EnableAutoConfiguration Auto-configuration} for HAPI FHIR.
|
||||||
*
|
*
|
||||||
* @author Mathieu Ouellet
|
* @author Mathieu Ouellet
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
|
@AutoConfigureAfter({DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
|
||||||
@EnableConfigurationProperties(FhirProperties.class)
|
@EnableConfigurationProperties(FhirProperties.class)
|
||||||
public class FhirAutoConfiguration {
|
public class FhirAutoConfiguration {
|
||||||
|
|
||||||
private final FhirProperties properties;
|
private final FhirProperties properties;
|
||||||
|
|
||||||
public FhirAutoConfiguration(FhirProperties properties) {
|
public FhirAutoConfiguration(FhirProperties properties) {
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public FhirContext fhirContext() {
|
public FhirContext fhirContext() {
|
||||||
FhirContext fhirContext = new FhirContext(properties.getVersion());
|
FhirContext fhirContext = new FhirContext(properties.getVersion());
|
||||||
return fhirContext;
|
return fhirContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@ConditionalOnClass(AbstractJaxRsProvider.class)
|
|
||||||
@EnableConfigurationProperties(FhirProperties.class)
|
|
||||||
@ConfigurationProperties("hapi.fhir.rest")
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
static class FhirRestfulServerConfiguration extends RestfulServer {
|
|
||||||
|
|
||||||
private final FhirProperties properties;
|
@Configuration
|
||||||
|
@ConditionalOnClass(AbstractJaxRsProvider.class)
|
||||||
|
@EnableConfigurationProperties(FhirProperties.class)
|
||||||
|
@ConfigurationProperties("hapi.fhir.rest")
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
static class FhirRestfulServerConfiguration extends RestfulServer {
|
||||||
|
|
||||||
private final FhirContext fhirContext;
|
private final FhirProperties properties;
|
||||||
|
|
||||||
private final List<IResourceProvider> resourceProviders;
|
private final FhirContext fhirContext;
|
||||||
|
|
||||||
private final IPagingProvider pagingProvider;
|
private final List<IResourceProvider> resourceProviders;
|
||||||
|
|
||||||
private final List<IServerInterceptor> interceptors;
|
private final IPagingProvider pagingProvider;
|
||||||
|
|
||||||
private final List<FhirRestfulServerCustomizer> customizers;
|
private final List<IServerInterceptor> interceptors;
|
||||||
|
|
||||||
public FhirRestfulServerConfiguration(
|
private final List<FhirRestfulServerCustomizer> customizers;
|
||||||
FhirProperties properties,
|
|
||||||
FhirContext fhirContext,
|
|
||||||
ObjectProvider<List<IResourceProvider>> resourceProviders,
|
|
||||||
ObjectProvider<IPagingProvider> pagingProvider,
|
|
||||||
ObjectProvider<List<IServerInterceptor>> interceptors,
|
|
||||||
ObjectProvider<List<FhirRestfulServerCustomizer>> customizers) {
|
|
||||||
this.properties = properties;
|
|
||||||
this.fhirContext = fhirContext;
|
|
||||||
this.resourceProviders = resourceProviders.getIfAvailable();
|
|
||||||
this.pagingProvider = pagingProvider.getIfAvailable();
|
|
||||||
this.interceptors = interceptors.getIfAvailable();
|
|
||||||
this.customizers = customizers.getIfAvailable();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
public FhirRestfulServerConfiguration(
|
||||||
public ServletRegistrationBean fhirServerRegistrationBean() {
|
FhirProperties properties,
|
||||||
ServletRegistrationBean registration = new ServletRegistrationBean(this, this.properties.getServer().getPath());
|
FhirContext fhirContext,
|
||||||
registration.setLoadOnStartup(1);
|
ObjectProvider<List<IResourceProvider>> resourceProviders,
|
||||||
return registration;
|
ObjectProvider<IPagingProvider> pagingProvider,
|
||||||
}
|
ObjectProvider<List<IServerInterceptor>> interceptors,
|
||||||
|
ObjectProvider<List<FhirRestfulServerCustomizer>> customizers) {
|
||||||
|
this.properties = properties;
|
||||||
|
this.fhirContext = fhirContext;
|
||||||
|
this.resourceProviders = resourceProviders.getIfAvailable();
|
||||||
|
this.pagingProvider = pagingProvider.getIfAvailable();
|
||||||
|
this.interceptors = interceptors.getIfAvailable();
|
||||||
|
this.customizers = customizers.getIfAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
private void customize() {
|
||||||
protected void initialize() throws ServletException {
|
if (this.customizers != null) {
|
||||||
super.initialize();
|
AnnotationAwareOrderComparator.sort(this.customizers);
|
||||||
|
for (FhirRestfulServerCustomizer customizer : this.customizers) {
|
||||||
|
customizer.customize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setFhirContext(this.fhirContext);
|
@Bean
|
||||||
setResourceProviders(this.resourceProviders);
|
public ServletRegistrationBean fhirServerRegistrationBean() {
|
||||||
setPagingProvider(this.pagingProvider);
|
ServletRegistrationBean registration = new ServletRegistrationBean(this, this.properties.getServer().getPath());
|
||||||
setInterceptors(this.interceptors);
|
registration.setLoadOnStartup(1);
|
||||||
|
return registration;
|
||||||
|
}
|
||||||
|
|
||||||
setServerAddressStrategy(new HardcodedServerAddressStrategy(this.properties.getServer().getPath()));
|
@Override
|
||||||
|
protected void initialize() throws ServletException {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
customize();
|
setFhirContext(this.fhirContext);
|
||||||
}
|
setResourceProviders(this.resourceProviders);
|
||||||
|
setPagingProvider(this.pagingProvider);
|
||||||
|
setInterceptors(this.interceptors);
|
||||||
|
|
||||||
private void customize() {
|
setServerAddressStrategy(new HardcodedServerAddressStrategy(this.properties.getServer().getPath()));
|
||||||
if (this.customizers != null) {
|
|
||||||
AnnotationAwareOrderComparator.sort(this.customizers);
|
|
||||||
for (FhirRestfulServerCustomizer customizer : this.customizers) {
|
|
||||||
customizer.customize(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
customize();
|
||||||
@ConditionalOnClass(BaseJpaProvider.class)
|
}
|
||||||
@ConditionalOnBean(DataSource.class)
|
}
|
||||||
@EnableConfigurationProperties(FhirProperties.class)
|
|
||||||
static class FhirJpaServerConfiguration {
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EntityScan("ca.uhn.fhir.jpa.entity")
|
@ConditionalOnClass(BaseJpaProvider.class)
|
||||||
@EnableJpaRepositories(basePackages = "ca.uhn.fhir.jpa.dao.data")
|
@ConditionalOnBean(DataSource.class)
|
||||||
static class FhirJpaDaoConfiguration {
|
@EnableConfigurationProperties(FhirProperties.class)
|
||||||
|
static class FhirJpaServerConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean()
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
@ConfigurationProperties("hapi.fhir.jpa")
|
public ScheduledExecutorFactoryBean scheduledExecutorService() {
|
||||||
public DaoConfig fhirDaoConfig() {
|
ScheduledExecutorFactoryBean b = new ScheduledExecutorFactoryBean();
|
||||||
DaoConfig fhirDaoConfig = new DaoConfig();
|
b.setPoolSize(5);
|
||||||
return fhirDaoConfig;
|
return b;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
@Bean
|
||||||
@ConditionalOnBean({ DaoConfig.class, RestfulServer.class })
|
@ConditionalOnMissingBean
|
||||||
@SuppressWarnings("rawtypes")
|
public AsyncTaskExecutor taskScheduler() {
|
||||||
static class RestfulServerCustomizer implements FhirRestfulServerCustomizer {
|
ConcurrentTaskScheduler retVal = new ConcurrentTaskScheduler();
|
||||||
|
retVal.setConcurrentExecutor(scheduledExecutorService().getObject());
|
||||||
|
retVal.setScheduledExecutor(scheduledExecutorService().getObject());
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
private final BaseJpaSystemProvider systemProviders;
|
@Configuration
|
||||||
|
@EntityScan("ca.uhn.fhir.jpa.entity")
|
||||||
|
@EnableJpaRepositories(basePackages = "ca.uhn.fhir.jpa.dao.data")
|
||||||
|
static class FhirJpaDaoConfiguration {
|
||||||
|
|
||||||
public RestfulServerCustomizer(ObjectProvider<BaseJpaSystemProvider> systemProviders) {
|
@Bean
|
||||||
this.systemProviders = systemProviders.getIfAvailable();
|
@ConditionalOnMissingBean
|
||||||
}
|
@ConfigurationProperties("hapi.fhir.jpa")
|
||||||
|
public DaoConfig fhirDaoConfig() {
|
||||||
|
DaoConfig fhirDaoConfig = new DaoConfig();
|
||||||
|
return fhirDaoConfig;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
}
|
||||||
public void customize(RestfulServer server) {
|
|
||||||
server.setPlainProviders(systemProviders);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnMissingBean(type = "ca.uhn.fhir.jpa.config.BaseConfig")
|
@ConditionalOnBean({DaoConfig.class, RestfulServer.class})
|
||||||
@ConditionalOnProperty(name = "hapi.fhir.version", havingValue = "DSTU3")
|
@SuppressWarnings("rawtypes")
|
||||||
static class Dstu3 extends BaseJavaConfigDstu3 {
|
static class RestfulServerCustomizer implements FhirRestfulServerCustomizer {
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
private final BaseJpaSystemProvider systemProviders;
|
||||||
@ConditionalOnMissingBean(type = "ca.uhn.fhir.jpa.config.BaseConfig")
|
|
||||||
@ConditionalOnProperty(name = "hapi.fhir.version", havingValue = "DSTU2")
|
|
||||||
static class Dstu2 extends BaseJavaConfigDstu2 {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
public RestfulServerCustomizer(ObjectProvider<BaseJpaSystemProvider> systemProviders) {
|
||||||
@Conditional(FhirValidationConfiguration.SchemaAvailableCondition.class)
|
this.systemProviders = systemProviders.getIfAvailable();
|
||||||
@ConditionalOnProperty(name = "hapi.fhir.validation.enabled", matchIfMissing = true)
|
}
|
||||||
static class FhirValidationConfiguration {
|
|
||||||
|
|
||||||
@Bean
|
@Override
|
||||||
@ConditionalOnMissingBean
|
public void customize(RestfulServer server) {
|
||||||
public RequestValidatingInterceptor requestValidatingInterceptor() {
|
server.setPlainProviders(systemProviders);
|
||||||
return new RequestValidatingInterceptor();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Configuration
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean(type = "ca.uhn.fhir.jpa.config.BaseConfig")
|
||||||
@ConditionalOnProperty(name = "hapi.fhir.validation.request-only", havingValue = "false")
|
@ConditionalOnProperty(name = "hapi.fhir.version", havingValue = "DSTU3")
|
||||||
public ResponseValidatingInterceptor responseValidatingInterceptor() {
|
static class Dstu3 extends BaseJavaConfigDstu3 {
|
||||||
return new ResponseValidatingInterceptor();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static class SchemaAvailableCondition extends ResourceCondition {
|
@Configuration
|
||||||
|
@ConditionalOnMissingBean(type = "ca.uhn.fhir.jpa.config.BaseConfig")
|
||||||
|
@ConditionalOnProperty(name = "hapi.fhir.version", havingValue = "DSTU2")
|
||||||
|
static class Dstu2 extends BaseJavaConfigDstu2 {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SchemaAvailableCondition() {
|
@Configuration
|
||||||
super("ValidationSchema",
|
@Conditional(FhirValidationConfiguration.SchemaAvailableCondition.class)
|
||||||
"hapi.fhir.validation",
|
@ConditionalOnProperty(name = "hapi.fhir.validation.enabled", matchIfMissing = true)
|
||||||
"schema-location",
|
static class FhirValidationConfiguration {
|
||||||
"classpath:/org/hl7/fhir/instance/model/schema",
|
|
||||||
"classpath:/org/hl7/fhir/dstu2016may/model/schema",
|
|
||||||
"classpath:/org/hl7/fhir/dstu3/model/schema");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
@Bean
|
||||||
@ConditionalOnProperty("hapi.fhir.server.url")
|
@ConditionalOnMissingBean
|
||||||
@EnableConfigurationProperties(FhirProperties.class)
|
public RequestValidatingInterceptor requestValidatingInterceptor() {
|
||||||
static class FhirRestfulClientConfiguration {
|
return new RequestValidatingInterceptor();
|
||||||
|
}
|
||||||
|
|
||||||
private final FhirProperties properties;
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
@ConditionalOnProperty(name = "hapi.fhir.validation.request-only", havingValue = "false")
|
||||||
|
public ResponseValidatingInterceptor responseValidatingInterceptor() {
|
||||||
|
return new ResponseValidatingInterceptor();
|
||||||
|
}
|
||||||
|
|
||||||
private final List<IClientInterceptor> clientInterceptors;
|
static class SchemaAvailableCondition extends ResourceCondition {
|
||||||
|
|
||||||
public FhirRestfulClientConfiguration(FhirProperties properties, ObjectProvider<List<IClientInterceptor>> clientInterceptors) {
|
SchemaAvailableCondition() {
|
||||||
this.properties = properties;
|
super("ValidationSchema",
|
||||||
this.clientInterceptors = clientInterceptors.getIfAvailable();
|
"hapi.fhir.validation",
|
||||||
}
|
"schema-location",
|
||||||
|
"classpath:/org/hl7/fhir/instance/model/schema",
|
||||||
|
"classpath:/org/hl7/fhir/dstu2016may/model/schema",
|
||||||
|
"classpath:/org/hl7/fhir/dstu3/model/schema");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Configuration
|
||||||
@ConditionalOnBean(IRestfulClientFactory.class)
|
@ConditionalOnProperty("hapi.fhir.server.url")
|
||||||
public IGenericClient fhirClient(final IRestfulClientFactory clientFactory) {
|
@EnableConfigurationProperties(FhirProperties.class)
|
||||||
IGenericClient fhirClient = clientFactory.newGenericClient(this.properties.getServer().getUrl());
|
static class FhirRestfulClientConfiguration {
|
||||||
if (!CollectionUtils.isEmpty(this.clientInterceptors)) {
|
|
||||||
for (IClientInterceptor interceptor : this.clientInterceptors) {
|
|
||||||
fhirClient.registerInterceptor(interceptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fhirClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
private final FhirProperties properties;
|
||||||
@ConditionalOnClass(HttpClient.class)
|
|
||||||
@ConditionalOnMissingClass("okhttp3.OkHttpClient")
|
|
||||||
static class Apache {
|
|
||||||
|
|
||||||
private final FhirContext context;
|
private final List<IClientInterceptor> clientInterceptors;
|
||||||
|
|
||||||
public Apache(FhirContext context) {
|
public FhirRestfulClientConfiguration(FhirProperties properties, ObjectProvider<List<IClientInterceptor>> clientInterceptors) {
|
||||||
this.context = context;
|
this.properties = properties;
|
||||||
}
|
this.clientInterceptors = clientInterceptors.getIfAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnBean(IRestfulClientFactory.class)
|
||||||
@ConfigurationProperties("hapi.fhir.rest.client.apache")
|
public IGenericClient fhirClient(final IRestfulClientFactory clientFactory) {
|
||||||
public IRestfulClientFactory fhirRestfulClientFactory() {
|
IGenericClient fhirClient = clientFactory.newGenericClient(this.properties.getServer().getUrl());
|
||||||
ApacheRestfulClientFactory restfulClientFactory = new ApacheRestfulClientFactory(this.context);
|
if (!CollectionUtils.isEmpty(this.clientInterceptors)) {
|
||||||
return restfulClientFactory;
|
for (IClientInterceptor interceptor : this.clientInterceptors) {
|
||||||
}
|
fhirClient.registerInterceptor(interceptor);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return fhirClient;
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnClass(OkHttpClient.class)
|
@ConditionalOnClass(HttpClient.class)
|
||||||
static class OkHttp {
|
@ConditionalOnMissingClass("okhttp3.OkHttpClient")
|
||||||
|
static class Apache {
|
||||||
|
|
||||||
private final FhirContext context;
|
private final FhirContext context;
|
||||||
|
|
||||||
public OkHttp(FhirContext context) {
|
public Apache(FhirContext context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
@ConfigurationProperties("hapi.fhir.rest.client.okhttp")
|
@ConfigurationProperties("hapi.fhir.rest.client.apache")
|
||||||
public IRestfulClientFactory fhirRestfulClientFactory() {
|
public IRestfulClientFactory fhirRestfulClientFactory() {
|
||||||
OkHttpRestfulClientFactory restfulClientFactory = new OkHttpRestfulClientFactory(this.context);
|
ApacheRestfulClientFactory restfulClientFactory = new ApacheRestfulClientFactory(this.context);
|
||||||
return restfulClientFactory;
|
return restfulClientFactory;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnClass(OkHttpClient.class)
|
||||||
|
static class OkHttp {
|
||||||
|
|
||||||
|
private final FhirContext context;
|
||||||
|
|
||||||
|
public OkHttp(FhirContext context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
@ConfigurationProperties("hapi.fhir.rest.client.okhttp")
|
||||||
|
public IRestfulClientFactory fhirRestfulClientFactory() {
|
||||||
|
OkHttpRestfulClientFactory restfulClientFactory = new OkHttpRestfulClientFactory(this.context);
|
||||||
|
return restfulClientFactory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue