diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/BundleUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/BundleUtil.java index 0793599ac57..0b2828200aa 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/BundleUtil.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/BundleUtil.java @@ -130,6 +130,16 @@ public class BundleUtil { return null; } + public static void setBundleType(FhirContext theContext, IBaseBundle theBundle, String theType) { + RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle); + BaseRuntimeChildDefinition entryChild = def.getChildByName("type"); + BaseRuntimeElementDefinition element = entryChild.getChildByName("type"); + IPrimitiveType typeInstance = (IPrimitiveType) element.newInstance(entryChild.getInstanceConstructorArguments()); + typeInstance.setValueAsString(theType); + + entryChild.getMutator().setValue(theBundle, typeInstance); + } + public static Integer getTotal(FhirContext theContext, IBaseBundle theBundle) { RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle); BaseRuntimeChildDefinition entryChild = def.getChildByName("total"); diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_3_0/2237-support-ibasebundle-for-xact-method-param.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_3_0/2237-support-ibasebundle-for-xact-method-param.yaml new file mode 100644 index 00000000000..cb78763b8d0 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_3_0/2237-support-ibasebundle-for-xact-method-param.yaml @@ -0,0 +1,5 @@ +--- +type: add +issue: 2237 +title: "It is now possible to use a parameter of type `IBaseResource` or `IBaseBundle` as the parameter + on a @Transaction method in a plain server." diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/TransactionParameter.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/TransactionParameter.java index d191ce5f8a1..e93ef4bfcb5 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/TransactionParameter.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/TransactionParameter.java @@ -50,7 +50,7 @@ public class TransactionParameter implements IParameter { private String createParameterTypeError(Method theMethod) { return "Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @" + TransactionParam.class.getName() - + " but is not of type List<" + IResource.class.getCanonicalName() + "> or Bundle"; + + " but is not of type Bundle, IBaseResource, IBaseBundle, or List<" + IResource.class.getCanonicalName() + ">"; } @Override @@ -66,10 +66,13 @@ public class TransactionParameter implements IParameter { if ("Bundle".equals(def.getName())) { myParamStyle = ParamStyle.RESOURCE_BUNDLE; myResourceBundleType = parameterType; - } else { - throw new ConfigurationException(createParameterTypeError(theMethod)); + return; } - } else { + } else if (theParameterType.equals(IBaseResource.class) || theParameterType.equals(IBaseBundle.class)) { + myParamStyle = ParamStyle.RESOURCE_BUNDLE; + myResourceBundleType = myContext.getResourceDefinition("Bundle").getImplementingClass(); + return; + } else if (theInnerCollectionType != null) { if (theInnerCollectionType.equals(List.class) == false) { throw new ConfigurationException(createParameterTypeError(theMethod)); } @@ -77,7 +80,10 @@ public class TransactionParameter implements IParameter { throw new ConfigurationException(createParameterTypeError(theMethod)); } myParamStyle = ParamStyle.RESOURCE_LIST; + return; } + + throw new ConfigurationException(createParameterTypeError(theMethod)); } @Override diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/TransactionServerTest.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/TransactionServerTest.java new file mode 100644 index 00000000000..d2c8b5094c0 --- /dev/null +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/TransactionServerTest.java @@ -0,0 +1,43 @@ +package ca.uhn.fhir.rest.server; + +import ca.uhn.fhir.context.FhirVersionEnum; +import ca.uhn.fhir.rest.annotation.Transaction; +import ca.uhn.fhir.rest.annotation.TransactionParam; +import ca.uhn.fhir.test.utilities.server.RestfulServerExtension; +import org.hl7.fhir.instance.model.api.IBaseBundle; +import org.hl7.fhir.r4.model.Bundle; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class TransactionServerTest { + + @RegisterExtension + public RestfulServerExtension myServerRule = new RestfulServerExtension(FhirVersionEnum.R4); + + + @Test + public void testTransactionParamIsInterface() { + + class MyProvider { + + @Transaction + public IBaseBundle transaction(@TransactionParam IBaseBundle theInput) { + return theInput; + } + + } + + myServerRule.getRestfulServer().registerProvider(new MyProvider()); + + Bundle input = new Bundle(); + input.setId("ABC"); + input.setType(Bundle.BundleType.TRANSACTION); + Bundle output = myServerRule.getFhirClient().transaction().withBundle(input).execute(); + + assertEquals("ABC", output.getIdElement().getIdPart()); + + } + +} diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/util/bundle/BundleUtilTest.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/util/bundle/BundleUtilTest.java index 0b887d0eef0..5801947ab06 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/util/bundle/BundleUtilTest.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/util/bundle/BundleUtilTest.java @@ -45,6 +45,15 @@ public class BundleUtilTest { assertEquals(null, BundleUtil.getTotal(ourCtx, b)); } + @Test + public void testSetType() { + Bundle b = new Bundle(); + BundleUtil.setBundleType(ourCtx, b, "transaction"); + assertEquals(Bundle.BundleType.TRANSACTION, b.getType()); + assertEquals("transaction", b.getTypeElement().getValueAsString()); + } + + @Test public void toListOfResourcesOfTypeTest() { Bundle bundle = new Bundle();