3

http://hapifhir.io/doc_custom_structures.html

this article discusses a DomainResource.

There are situations however when you might want to create an entirely custom resource type. This feature should be used only if there is no other option, since it means you are creating a resource type that will not be interoperable with other FHIR implementations.

I've implemented the code verbatum. (I show the classes below (with no "guts" just for brevity) (full code at the url))

/**
 * This is an example of a custom resource that also uses a custom
 * datatype.
 * 
 * Note that we are extensing DomainResource for an STU3
 * resource. For DSTU2 it would be BaseResource. 
 */
@ResourceDef(name = "CustomResource", profile = "http://hl7.org/fhir/profiles/custom-resource")
public class CustomResource extends DomainResource {
}

and

/**
 * This is an example of a custom datatype. 
 * 
 * This is an STU3 example so it extends Type and implements ICompositeType. For
 * DSTU2 it would extend BaseIdentifiableElement and implement ICompositeDatatype.
 */
@DatatypeDef(name="CustomDatatype")
public class CustomDatatype extends Type implements ICompositeType {
}

And I've "registered it" in my code base:

        if (null != this.fhirContext)
        {
            this.fhirContext.registerCustomType(CustomResource.class);
            this.fhirContext.registerCustomType(CustomDatatype.class);
        }

(~trying to follow the instructions from the URL above)

// Create a context. Note that we declare the custom types we'll be using
// on the context before actually using them
FhirContext ctx = FhirContext.forDstu3();
ctx.registerCustomType(CustomResource.class);
ctx.registerCustomType(CustomDatatype.class);

// Now let's create an instance of our custom resource type
// and populate it with some data
CustomResource res = new CustomResource();

// Add some values, including our custom datatype
DateType value0 = new DateType("2015-01-01");
res.getTelevision().add(value0);

CustomDatatype value1 = new CustomDatatype();
value1.setDate(new DateTimeType(new Date()));
value1.setKittens(new StringType("FOO"));
res.getTelevision().add(value1);

res.setDogs(new StringType("Some Dogs"));

// Now let's serialize our instance
String output = ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(res);
System.out.println(output);

But that looks like a console-app usage of two objects...not how to wire it into the fhir-server.

I've been trying for 3 hours now to figure out what URL to use.

some things I've tried:

http://127.0.0.1:8080/fhir/CustomResource

http://127.0.0.1:8080/fhir/profiles/custom-resource

http://127.0.0.1:8080/fhir/custom-resource

to no avail...

What is the URL?

And how do I populate the values for it?

granadaCoder
  • 26,328
  • 10
  • 113
  • 146
  • Creating the resource does not create a URL by default. Have you set up and configured a RESTful Server? if so that is where you would add access to your custom resources and types http://hapifhir.io/doc_rest_server.html. – Daniels Jan 14 '19 at 00:51
  • Yes I gave my fhir server working with default resouces like Patient, etc – granadaCoder Jan 14 '19 at 02:15
  • fhirContext is "my" code...where I register the items....thus why I think a URL should work – granadaCoder Jan 14 '19 at 02:18
  • 1
    To register the resource to the REST server you need to create ResourceProvider classes for your custom resource and register that ResourceProvider to the server as outlined in initial link i provided, if you are using the sample JPA server this work has been done for the default resources as outlined here http://hapifhir.io/doc_jpa.html but you will still need to add for your own custom resource. – Daniels Jan 14 '19 at 04:02
  • 1
    Thank you Daniels. Now I "get it". I still need to create an IResourceProvider for the new custom resource...and add some methods there. So this was a "duh" moment. I wish the documentation just added that little bit. Sometimes you're so far in the trees, can't see the forest. I'll post my basic working example soon. – granadaCoder Jan 14 '19 at 16:47

1 Answers1

2

Ok.

So the CustomResource still needs its own IResourceProvider. (thanks to daniels in the comments of the original question)

Here is a basic working example.

You'll do everything I listed in the original question AND you'll make and register an IResourceProvider for the new customresource.

new IResourceProvider

package mystuff.resourceproviders;

import org.hl7.fhir.dstu3.model.DateType;
import org.hl7.fhir.dstu3.model.IdType;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.rest.server.IResourceProvider;
import mystuff.CustomDatatype;
import mystuff.CustomResource;
import org.hl7.fhir.dstu3.model.DateTimeType;
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.instance.model.api.IBaseResource;

import java.util.Date;

public class CustomResourceProvider implements IResourceProvider {


    @Override
    public Class<? extends IBaseResource> getResourceType() {
        return CustomResource.class;
    }


    /* the IdType (datatype) will be different based on STU2 or STU3.  STU3 version below */
    @Read()
    public CustomResource getResourceById(@IdParam IdType theId) {
        // Now let's create an instance of our custom resource type
        // and populate it with some data
        CustomResource res = new CustomResource();
        res.setId(theId);

        // Add some values, including our custom datatype
        DateType value0 = new DateType("2015-01-01");
        res.getTelevision().add(value0);

        CustomDatatype value1 = new CustomDatatype();
        value1.setDate(new DateTimeType(new Date()));
        value1.setKittens(new StringType("FOO"));
        res.getTelevision().add(value1);

        res.setDogs(new StringType("Some Dogs"));
        return res;
    }
}

then you'll register this (as documented here):

http://hapifhir.io/doc_rest_server.html#_toc_create_a_server

instead of this:

   @Override
   protected void initialize() throws ServletException {
      /*
       * The servlet defines any number of resource providers, and
       * configures itself to use them by calling
       * setResourceProviders()
       */
      List<IResourceProvider> resourceProviders = new ArrayList<IResourceProvider>();
      resourceProviders.add(new RestfulPatientResourceProvider());
      resourceProviders.add(new RestfulObservationResourceProvider());
      setResourceProviders(resourceProviders);
   }

you'll have something like this

   @Override
   protected void initialize() throws ServletException {
      /*
       * The servlet defines any number of resource providers, and
       * configures itself to use them by calling
       * setResourceProviders()
       */
      List<IResourceProvider> resourceProviders = new ArrayList<IResourceProvider>();
      resourceProviders.add(new CustomResourceProvider());
      setResourceProviders(resourceProviders);
   }

URL for testing this (most probable local development url that is)

http://127.0.0.1:8080/fhir/CustomResource/12345

and you'll get back this JSON response.

{
    "resourceType": "CustomResource",
    "id": "12345",
    "meta": {
        "profile": [
            "http://hl7.org/fhir/profiles/custom-resource"
        ]
    },
    "televisionDate": [
        "2015-01-01"
    ],
    "televisionCustomDatatype": [
        {
            "date": "2019-01-14T11:49:44-05:00",
            "kittens": "FOO"
        }
    ],
    "dogs": "Some Dogs"
}
granadaCoder
  • 26,328
  • 10
  • 113
  • 146