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 299cf0744be..51591ed0fec 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
@@ -91,10 +91,13 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.jar.Manifest;
@@ -106,7 +109,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
/**
* This class is the central class for the HAPI FHIR Plain Server framework.
- *
+ *
* See HAPI FHIR Plain Server
* for information on how to use this framework.
*/
@@ -184,7 +187,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer> getProviderMethodBindings(Object theProvider) {
+ Set> retVal = new HashSet<>();
+ for (ResourceBinding resourceBinding : getResourceBindings()) {
+ for (BaseMethodBinding> methodBinding : resourceBinding.getMethodBindings()) {
+ if (theProvider.equals(methodBinding.getProvider())) {
+ retVal.add(methodBinding);
+ }
+ }
+ }
+
+ return retVal;
+ }
+
/**
* Provides the resource providers for this server
*/
@@ -1001,8 +1017,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer resourceNames, Object theProvider) {
for (String resourceName : resourceNames) {
- myResourceNameToBinding.remove(resourceName);
+ ResourceBinding resourceBinding = myResourceNameToBinding.get(resourceName);
+ if (resourceBinding == null) {
+ continue;
+ }
+
+ for (Iterator> it = resourceBinding.getMethodBindings().iterator(); it.hasNext(); ) {
+ BaseMethodBinding> binding = it.next();
+ if (theProvider.equals(binding.getProvider())) {
+ it.remove();
+ ourLog.info("{} binding of {} was removed", resourceName, binding);
+ }
+ }
+
+ if (resourceBinding.getMethodBindings().isEmpty()) {
+ myResourceNameToBinding.remove(resourceName);
+ }
}
}
diff --git a/hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/RestfulServerTest.java b/hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/RestfulServerTest.java
index a0ce231ff05..95c67bec9bb 100644
--- a/hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/RestfulServerTest.java
+++ b/hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/RestfulServerTest.java
@@ -3,14 +3,19 @@ package ca.uhn.fhir.rest.server;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
+import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.rest.annotation.Create;
import ca.uhn.fhir.rest.annotation.Metadata;
+import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.ResourceParam;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.server.IFhirVersionServer;
import ca.uhn.fhir.rest.api.server.RequestDetails;
+import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseConformance;
+import org.hl7.fhir.instance.model.api.IBaseMetaType;
import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -21,12 +26,10 @@ import org.mockito.junit.jupiter.MockitoExtension;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
+import java.util.List;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
public class RestfulServerTest {
@@ -43,6 +46,32 @@ public class RestfulServerTest {
restfulServer.init();
}
+ private void mockResource(Class theClass) {
+ RuntimeResourceDefinition resourceDefinitionMock = mock(RuntimeResourceDefinition.class);
+ String className = theClass.getSimpleName();
+ lenient().when(resourceDefinitionMock.getName()).thenReturn(className);
+ lenient().when(myCtx.getResourceDefinition(className)).thenReturn(resourceDefinitionMock);
+ lenient().when(myCtx.getResourceType(theClass)).thenReturn(className);
+ }
+
+ @Test
+ public void testRegisterProvidersWithMethodBindings() {
+ mockResource(MyResource.class);
+ mockResource(MyResource2.class);
+
+ MyProvider provider = new MyProvider();
+ restfulServer.registerProvider(provider);
+ MyProvider2 provider2 = new MyProvider2();
+ restfulServer.registerProvider(provider2);
+
+ assertFalse(restfulServer.getProviderMethodBindings(provider).isEmpty());
+ assertFalse(restfulServer.getProviderMethodBindings(provider2).isEmpty());
+
+ restfulServer.unregisterProvider(provider);
+ assertTrue(restfulServer.getProviderMethodBindings(provider).isEmpty());
+ assertFalse(restfulServer.getProviderMethodBindings(provider2).isEmpty());
+ }
+
@Test
public void testRegisterProviders() {
//test register Plain Provider
@@ -123,4 +152,89 @@ public class RestfulServerTest {
}
}
+ private static class MyProvider implements IResourceProvider {
+ @Operation(name = "SHOW_ME_THE_MONEY", typeName = "MyResource")
+ public IBaseBundle match() {
+ return mock(IBaseBundle.class);
+ }
+
+ @Override
+ public Class extends IBaseResource> getResourceType() {
+ return MyResource.class;
+ }
+ }
+
+ private static class MyProvider2 implements IResourceProvider {
+ @Operation(name = "SHOW_ME_MORE_MONEY", typeName = "MyResource2")
+ public IBaseBundle match() {
+ return mock(IBaseBundle.class);
+ }
+
+ @Override
+ public Class extends IBaseResource> getResourceType() {
+ return MyResource2.class;
+ }
+ }
+
+ private static class MyResource implements IBaseResource {
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ @Override
+ public boolean hasFormatComment() {
+ return false;
+ }
+
+ @Override
+ public List getFormatCommentsPre() {
+ return null;
+ }
+
+ @Override
+ public List getFormatCommentsPost() {
+ return null;
+ }
+
+ @Override
+ public Object getUserData(String theName) {
+ return null;
+ }
+
+ @Override
+ public void setUserData(String theName, Object theValue) {
+
+ }
+
+ @Override
+ public IBaseMetaType getMeta() {
+ return null;
+ }
+
+ @Override
+ public IIdType getIdElement() {
+ return null;
+ }
+
+ @Override
+ public IBaseResource setId(String theId) {
+ return null;
+ }
+
+ @Override
+ public IBaseResource setId(IIdType theId) {
+ return null;
+ }
+
+ @Override
+ public FhirVersionEnum getStructureFhirVersionEnum() {
+ return null;
+ }
+ }
+
+ private static class MyResource2 extends MyResource {
+ }
+
}