diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java index 8306125dfd3..016ad9fa615 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java @@ -58,6 +58,7 @@ import ca.uhn.fhir.util.*; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Charsets; import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.common.hash.HashFunction; import com.google.common.hash.Hashing; @@ -85,6 +86,7 @@ import org.springframework.stereotype.Repository; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.support.TransactionTemplate; +import javax.annotation.PostConstruct; import javax.persistence.*; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; @@ -727,23 +729,32 @@ public abstract class BaseHapiFhirDao implements IDao, private Map, IFhirResourceDao> getDaos() { if (myResourceTypeToDao == null) { - Map, IFhirResourceDao> theResourceTypeToDao = new HashMap<>(); + Map, IFhirResourceDao> resourceTypeToDao = new HashMap<>(); + Map daos = myApplicationContext.getBeansOfType(IFhirResourceDao.class, false, false); + + String[] beanNames = myApplicationContext.getBeanNamesForType(IFhirResourceDao.class); + for (IFhirResourceDao next : daos.values()) { - theResourceTypeToDao.put(next.getResourceType(), next); + resourceTypeToDao.put(next.getResourceType(), next); } if (this instanceof IFhirResourceDao) { IFhirResourceDao thiz = (IFhirResourceDao) this; - theResourceTypeToDao.put(thiz.getResourceType(), thiz); + resourceTypeToDao.put(thiz.getResourceType(), thiz); } - myResourceTypeToDao = theResourceTypeToDao; + myResourceTypeToDao = resourceTypeToDao; } return Collections.unmodifiableMap(myResourceTypeToDao); } + @PostConstruct + public void startClearCaches() { + myResourceTypeToDao = null; + } + protected Set extractSearchParamCoords(ResourceTable theEntity, IBaseResource theResource) { return mySearchParamExtractor.extractSearchParamCoords(theEntity, theResource); @@ -948,7 +959,14 @@ public abstract class BaseHapiFhirDao implements IDao, @Override public void setApplicationContext(ApplicationContext theApplicationContext) throws BeansException { - myApplicationContext = theApplicationContext; + /* + * We do a null check here because Smile's module system tries to + * initialize the application context twice if two modules depend on + * the persistence module. The second time sets the dependency's appctx. + */ + if (myApplicationContext == null) { + myApplicationContext = theApplicationContext; + } } public void setConfig(DaoConfig theConfig) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java index 10fc0d040e8..6cff70e1f1e 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java @@ -1336,5 +1336,9 @@ public abstract class BaseHapiFhirResourceDao extends B } } + @PostConstruct + public void start() { + ourLog.info("Starting resource DAO for type: {}", getResourceName()); + } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java index 7f40beeead0..58d9d74ad1c 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java @@ -305,7 +305,7 @@ public abstract class BaseHapiFhirSystemDao extends BaseHapiFhirDao { * * See the class documentation for an important note if you are extending this class */ - public abstract T getServerConformance(HttpServletRequest theRequest); + T getServerConformance(HttpServletRequest theRequest); /** * This setter is needed in implementation classes (along with @@ -40,5 +40,5 @@ public interface IServerConformanceProvider { * * @param theRestfulServer */ - public void setRestfulServer(RestfulServer theRestfulServer); + void setRestfulServer(RestfulServer theRestfulServer); } diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java index 99b2d0ea27a..dfad1a42e97 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java @@ -9,9 +9,9 @@ package ca.uhn.fhir.rest.server; * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,6 +26,7 @@ import ca.uhn.fhir.context.ProvidedResourceScanner; import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.api.AddProfileTagEnum; import ca.uhn.fhir.context.api.BundleInclusionRule; +import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.rest.annotation.Destroy; import ca.uhn.fhir.rest.annotation.IdParam; @@ -125,6 +126,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer theList) { + public void setInterceptors(IServerInterceptor... theList) { myInterceptors.clear(); if (theList != null) { - myInterceptors.addAll(theList); + myInterceptors.addAll(Arrays.asList(theList)); } } @@ -606,8 +603,11 @@ public class RestfulServer extends HttpServlet implements IRestfulServer theProviders) { + myPlainProviders.clear(); + if (theProviders != null) { + myPlainProviders.addAll(theProviders); + } } /** @@ -637,10 +637,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer theResourceProviders) { myResourceProviders.clear(); if (theResourceProviders != null) { - myResourceProviders.addAll(Arrays.asList(theResourceProviders)); + myResourceProviders.addAll(theResourceProviders); } } @@ -1518,10 +1518,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer theList) { myInterceptors.clear(); if (theList != null) { - myInterceptors.addAll(Arrays.asList(theList)); + myInterceptors.addAll(theList); } } @@ -1530,11 +1530,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer theProviders) { - myPlainProviders.clear(); - if (theProviders != null) { - myPlainProviders.addAll(theProviders); - } + public void setPlainProviders(Object... theProv) { + setPlainProviders(Arrays.asList(theProv)); } /** @@ -1552,10 +1549,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer theResourceProviders) { + public void setResourceProviders(IResourceProvider... theResourceProviders) { myResourceProviders.clear(); if (theResourceProviders != null) { - myResourceProviders.addAll(theResourceProviders); + myResourceProviders.addAll(Arrays.asList(theResourceProviders)); } } diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestulfulServerConfiguration.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestulfulServerConfiguration.java index 1574ccb41a9..a74dae2a153 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestulfulServerConfiguration.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestulfulServerConfiguration.java @@ -21,11 +21,13 @@ package ca.uhn.fhir.rest.server; */ import java.util.Collection; +import java.util.Date; import java.util.List; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.rest.server.method.BaseMethodBinding; import ca.uhn.fhir.util.VersionUtil; +import org.hl7.fhir.instance.model.api.IPrimitiveType; import static org.apache.commons.lang3.StringUtils.isBlank; @@ -38,7 +40,7 @@ public class RestulfulServerConfiguration { private String serverName = "HAPI FHIR"; private FhirContext fhirContext; private IServerAddressStrategy serverAddressStrategy; - private String conformanceDate; + private IPrimitiveType myConformanceDate; /** * Constructor @@ -73,11 +75,10 @@ public class RestulfulServerConfiguration { } /** - * Set the serverBindings - * @param serverBindings the serverBindings to set + * Set the theServerBindings */ - public RestulfulServerConfiguration setServerBindings(List> serverBindings) { - this.serverBindings = serverBindings; + public RestulfulServerConfiguration setServerBindings(List> theServerBindings) { + this.serverBindings = theServerBindings; return this; } @@ -166,23 +167,25 @@ public class RestulfulServerConfiguration { */ public void setServerAddressStrategy(IServerAddressStrategy serverAddressStrategy) { this.serverAddressStrategy = serverAddressStrategy; - } + } - - /** - * Get the conformanceDate - * @return the conformanceDate - */ - public String getConformanceDate() { - return conformanceDate; + + /** + * Get the date that will be specified in the conformance profile + * exported by this server. Typically this would be populated with + * an InstanceType. + */ + public IPrimitiveType getConformanceDate() { + return myConformanceDate; } /** - * Set the conformanceDate - * @param conformanceDate the conformanceDate to set + * Set the date that will be specified in the conformance profile + * exported by this server. Typically this would be populated with + * an InstanceType. */ - public void setConformanceDate(String conformanceDate) { - this.conformanceDate = conformanceDate; + public void setConformanceDate(IPrimitiveType theConformanceDate) { + myConformanceDate = theConformanceDate; } } diff --git a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/rest/server/ServerConformanceProvider.java b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/rest/server/ServerConformanceProvider.java index 21dbc8d016f..efce3ae8560 100644 --- a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/rest/server/ServerConformanceProvider.java +++ b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/rest/server/ServerConformanceProvider.java @@ -49,6 +49,7 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.method.*; import ca.uhn.fhir.rest.server.method.OperationMethodBinding.ReturnType; import ca.uhn.fhir.rest.server.method.SearchParameter; +import org.hl7.fhir.instance.model.api.IPrimitiveType; /** * Server FHIR Provider which serves the conformance statement for a RESTful server implementation @@ -132,10 +133,10 @@ public class ServerConformanceProvider implements IServerConformanceProvider buildDate = getServerConfiguration().getConformanceDate(); + if (buildDate != null && buildDate.getValue() != null) { try { - return new DateTimeType(buildDate); + return new DateTimeType(buildDate.getValueAsString()); } catch (DataFormatException e) { // fall through } diff --git a/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/ServerConformanceProvider.java b/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/ServerConformanceProvider.java index 6016ba4a979..6e03d0428e5 100644 --- a/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/ServerConformanceProvider.java +++ b/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/ServerConformanceProvider.java @@ -30,6 +30,7 @@ import ca.uhn.fhir.rest.server.method.*; import ca.uhn.fhir.rest.server.method.OperationMethodBinding.ReturnType; import org.apache.commons.lang3.StringUtils; import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IPrimitiveType; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; @@ -136,10 +137,10 @@ public class ServerConformanceProvider implements IServerConformanceProvider buildDate = getServerConfiguration().getConformanceDate(); + if (buildDate != null && buildDate.getValue() != null) { try { - return new DateTimeDt(buildDate); + return new DateTimeDt(buildDate.getValueAsString()); } catch (DataFormatException e) { // fall through } diff --git a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/ServerCapabilityStatementProvider.java b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/ServerCapabilityStatementProvider.java index 66c7fa2c0d3..85cdf11af2c 100644 --- a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/ServerCapabilityStatementProvider.java +++ b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/ServerCapabilityStatementProvider.java @@ -27,6 +27,7 @@ import org.hl7.fhir.dstu3.model.OperationDefinition.OperationKind; import org.hl7.fhir.dstu3.model.OperationDefinition.OperationParameterUse; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IPrimitiveType; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; @@ -76,7 +77,7 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv private Callable myServerConfiguration; /** - * No-arg constructor and seetter so that the ServerConfirmanceProvider can be Spring-wired with the RestfulService avoiding the potential reference cycle that would happen. + * No-arg constructor and setter so that the ServerConformanceProvider can be Spring-wired with the RestfulService avoiding the potential reference cycle that would happen. */ public ServerCapabilityStatementProvider() { super(); @@ -139,10 +140,10 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv } private DateTimeType conformanceDate() { - String buildDate = getServerConfiguration().getConformanceDate(); - if (buildDate != null) { + IPrimitiveType buildDate = getServerConfiguration().getConformanceDate(); + if (buildDate != null && buildDate.getValue() != null) { try { - return new DateTimeType(buildDate); + return new DateTimeType(buildDate.getValueAsString()); } catch (DataFormatException e) { // fall through } diff --git a/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/hapi/rest/server/ServerCapabilityStatementProviderDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/hapi/rest/server/ServerCapabilityStatementProviderDstu3Test.java index 4ae3b38ff23..766bdabb910 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/hapi/rest/server/ServerCapabilityStatementProviderDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/hapi/rest/server/ServerCapabilityStatementProviderDstu3Test.java @@ -15,6 +15,7 @@ import java.util.*; import javax.servlet.ServletConfig; import javax.servlet.http.HttpServletRequest; +import ca.uhn.fhir.model.primitive.InstantDt; import org.hl7.fhir.dstu3.model.*; import org.hl7.fhir.dstu3.model.CapabilityStatement.*; import org.hl7.fhir.instance.model.api.IBaseResource; @@ -527,29 +528,42 @@ public class ServerCapabilityStatementProviderDstu3Test { @Test public void testSearchReferenceParameterWithList() throws Exception { - RestfulServer rsNoType = new RestfulServer(ourCtx); + RestfulServer rsNoType = new RestfulServer(ourCtx){ + @Override + public RestulfulServerConfiguration createConfiguration() { + RestulfulServerConfiguration retVal = super.createConfiguration(); + retVal.setConformanceDate(new InstantDt("2011-02-22T11:22:33Z")); + return retVal; + } + }; rsNoType.registerProvider(new SearchProviderWithListNoType()); ServerCapabilityStatementProvider scNoType = new ServerCapabilityStatementProvider(rsNoType); rsNoType.setServerConformanceProvider(scNoType); rsNoType.init(createServletConfig()); - scNoType.getServerConfiguration().setConformanceDate("2011-02-22T11:22:33Z"); - + CapabilityStatement conformance = scNoType.getServerConformance(createHttpServletRequest()); String confNoType = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance); ourLog.info(confNoType); - RestfulServer rsWithType = new RestfulServer(ourCtx); + RestfulServer rsWithType = new RestfulServer(ourCtx){ + @Override + public RestulfulServerConfiguration createConfiguration() { + RestulfulServerConfiguration retVal = super.createConfiguration(); + retVal.setConformanceDate(new InstantDt("2011-02-22T11:22:33Z")); + return retVal; + } + }; rsWithType.registerProvider(new SearchProviderWithListWithType()); ServerCapabilityStatementProvider scWithType = new ServerCapabilityStatementProvider(rsWithType); rsWithType.setServerConformanceProvider(scWithType); rsWithType.init(createServletConfig()); - scWithType.getServerConfiguration().setConformanceDate("2011-02-22T11:22:33Z"); CapabilityStatement conformanceWithType = scWithType.getServerConformance(createHttpServletRequest()); String confWithType = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(conformanceWithType); ourLog.info(confWithType); assertEquals(confNoType, confWithType); + assertThat(confNoType, containsString("")); } @Test diff --git a/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/conf/ServerConformanceProvider.java b/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/conf/ServerConformanceProvider.java index e0350896ace..895db7121db 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/conf/ServerConformanceProvider.java +++ b/hapi-fhir-structures-hl7org-dstu2/src/main/java/org/hl7/fhir/instance/conf/ServerConformanceProvider.java @@ -50,6 +50,7 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.method.*; import ca.uhn.fhir.rest.server.method.OperationMethodBinding.ReturnType; import ca.uhn.fhir.rest.server.method.SearchParameter; +import org.hl7.fhir.instance.model.api.IPrimitiveType; /** * Server FHIR Provider which serves the conformance statement for a RESTful @@ -314,10 +315,10 @@ public class ServerConformanceProvider implements IServerConformanceProvider buildDate = getServerConfiguration().getConformanceDate(); + if (buildDate != null && buildDate.getValue() != null) { try { - return new DateTimeType(buildDate); + return new DateTimeType(buildDate.getValueAsString()); } catch (DataFormatException e) { // fall through } diff --git a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/rest/server/ServerCapabilityStatementProvider.java b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/rest/server/ServerCapabilityStatementProvider.java index 940587eeebe..e0947c9f014 100644 --- a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/rest/server/ServerCapabilityStatementProvider.java +++ b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/rest/server/ServerCapabilityStatementProvider.java @@ -21,6 +21,7 @@ import ca.uhn.fhir.rest.server.method.SearchParameter; import org.apache.commons.lang3.StringUtils; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.r4.model.*; import org.hl7.fhir.r4.model.CapabilityStatement.*; import org.hl7.fhir.r4.model.Enumerations.PublicationStatus; @@ -139,10 +140,10 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv } private DateTimeType conformanceDate() { - String buildDate = getServerConfiguration().getConformanceDate(); - if (buildDate != null) { + IPrimitiveType buildDate = getServerConfiguration().getConformanceDate(); + if (buildDate != null && buildDate.getValue() != null) { try { - return new DateTimeType(buildDate); + return new DateTimeType(buildDate.getValueAsString()); } catch (DataFormatException e) { // fall through }