diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/IServerConformanceProvider.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/IServerConformanceProvider.java index 0f5f060403d..184a8122e9f 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/IServerConformanceProvider.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/IServerConformanceProvider.java @@ -33,4 +33,12 @@ public interface IServerConformanceProvider { */ public abstract T getServerConformance(HttpServletRequest theRequest); + /** + * This setter is needed in implementation classes (along with + * a no-arg constructor) to avoid reference cycles in the + * Spring wiring of a RestfulServer instance. + * + * @param theRestfulServer + */ + public void setRestfulServer (RestfulServer theRestfulServer); } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java index 67d9062a327..32ce902e9ea 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java @@ -1086,6 +1086,19 @@ public class RestfulServer extends HttpServlet { if (myStarted) { throw new IllegalStateException("Server is already started"); } + + // call the setRestfulServer() method to point the Conformance + // Provider to this server instance. This is done to avoid + // passing the server into the constructor. Having that sort + // of cross linkage causes reference cycles in Spring wiring + try { + Method setRestfulServer = theServerConformanceProvider.getClass().getMethod("setRestfulServer", new Class[]{RestfulServer.class}); + if (setRestfulServer != null) { + setRestfulServer.invoke(theServerConformanceProvider, new Object[]{this}); + } + } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + ourLog.warn("Error calling IServerConformanceProvider.setRestfulServer", e); + } myServerConformanceProvider = theServerConformanceProvider; } diff --git a/hapi-fhir-structures-dstu/src/main/java/ca/uhn/fhir/rest/server/provider/ServerConformanceProvider.java b/hapi-fhir-structures-dstu/src/main/java/ca/uhn/fhir/rest/server/provider/ServerConformanceProvider.java index 0ff78156c8f..976c46c0cce 100644 --- a/hapi-fhir-structures-dstu/src/main/java/ca/uhn/fhir/rest/server/provider/ServerConformanceProvider.java +++ b/hapi-fhir-structures-dstu/src/main/java/ca/uhn/fhir/rest/server/provider/ServerConformanceProvider.java @@ -77,11 +77,25 @@ public class ServerConformanceProvider implements IServerConformanceProvider myOperationBindingToName; private HashMap> myOperationNameToBindings; private String myPublisher = "Not provided"; - private final RestfulServer myRestfulServer; + private RestfulServer myRestfulServer; public ServerConformanceProvider(RestfulServer theRestfulServer) { myRestfulServer = theRestfulServer; } + + /* + * Add a no-arg constructor and seetter so that the + * ServerConfirmanceProvider can be Spring-wired with + * the RestfulService avoiding the potential reference + * cycle that would happen. + */ + public ServerConformanceProvider () { + super(); + } + + public void setRestfulServer (RestfulServer theRestfulServer) { + myRestfulServer = theRestfulServer; + } private void checkBindingForSystemOps(Rest rest, Set systemOps, BaseMethodBinding nextMethodBinding) { if (nextMethodBinding.getSystemOperationType() != null) { 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 496a54efb6f..514cc23939e 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 @@ -94,11 +94,25 @@ public class ServerConformanceProvider implements IServerConformanceProvider myOperationBindingToName; private HashMap> myOperationNameToBindings; private String myPublisher = "Not provided"; - private final RestfulServer myRestfulServer; + private RestfulServer myRestfulServer; public ServerConformanceProvider(RestfulServer theRestfulServer) { myRestfulServer = theRestfulServer; } + + /* + * Add a no-arg constructor and seetter so that the + * ServerConfirmanceProvider can be Spring-wired with + * the RestfulService avoiding the potential reference + * cycle that would happen. + */ + public ServerConformanceProvider () { + super(); + } + + public void setRestfulServer (RestfulServer theRestfulServer) { + myRestfulServer = theRestfulServer; + } private void checkBindingForSystemOps(ConformanceRestComponent rest, Set systemOps, BaseMethodBinding nextMethodBinding) { if (nextMethodBinding.getSystemOperationType() != null) {