Search in sources :

Example 1 with Subscription

use of org.hl7.fhir.r4.model.Subscription in project drug-formulary-ri by HL7-DaVinci.

the class JpaRestfulServer method initialize.

@SuppressWarnings("unchecked")
@Override
protected void initialize() throws ServletException {
    super.initialize();
    /*
     * Create a FhirContext object that uses the version of FHIR
     * specified in the properties file.
     */
    ApplicationContext appCtx = (ApplicationContext) getServletContext().getAttribute("org.springframework.web.context.WebApplicationContext.ROOT");
    // Customize supported resource types
    Set<String> supportedResourceTypes = HapiProperties.getSupportedResourceTypes();
    if (!supportedResourceTypes.isEmpty() && !supportedResourceTypes.contains("SearchParameter")) {
        supportedResourceTypes.add("SearchParameter");
    }
    if (!supportedResourceTypes.isEmpty()) {
        DaoRegistry daoRegistry = appCtx.getBean(DaoRegistry.class);
        daoRegistry.setSupportedResourceTypes(supportedResourceTypes);
    }
    /*
     * ResourceProviders are fetched from the Spring context
     */
    FhirVersionEnum fhirVersion = HapiProperties.getFhirVersion();
    ResourceProviderFactory resourceProviders;
    Object systemProvider;
    if (fhirVersion == FhirVersionEnum.DSTU2) {
        resourceProviders = appCtx.getBean("myResourceProvidersDstu2", ResourceProviderFactory.class);
        systemProvider = appCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class);
    } else if (fhirVersion == FhirVersionEnum.DSTU3) {
        resourceProviders = appCtx.getBean("myResourceProvidersDstu3", ResourceProviderFactory.class);
        systemProvider = appCtx.getBean("mySystemProviderDstu3", JpaSystemProviderDstu3.class);
    } else if (fhirVersion == FhirVersionEnum.R4) {
        resourceProviders = appCtx.getBean("myResourceProvidersR4", ResourceProviderFactory.class);
        systemProvider = appCtx.getBean("mySystemProviderR4", JpaSystemProviderR4.class);
    } else if (fhirVersion == FhirVersionEnum.R5) {
        resourceProviders = appCtx.getBean("myResourceProvidersR5", ResourceProviderFactory.class);
        systemProvider = appCtx.getBean("mySystemProviderR5", JpaSystemProviderR5.class);
    } else {
        throw new IllegalStateException();
    }
    setFhirContext(appCtx.getBean(FhirContext.class));
    registerProviders(resourceProviders.createProviders());
    registerProvider(systemProvider);
    /*
     * The conformance provider exports the supported resources, search parameters,
     * etc for
     * this server. The JPA version adds resourceProviders counts to the exported
     * statement, so it
     * is a nice addition.
     *
     * You can also create your own subclass of the conformance provider if you need
     * to
     * provide further customization of your server's CapabilityStatement
     */
    IFhirSystemDao<org.hl7.fhir.r4.model.Bundle, org.hl7.fhir.r4.model.Meta> systemDao = appCtx.getBean("mySystemDaoR4", IFhirSystemDao.class);
    MetadataProvider metadata = new MetadataProvider(this, systemDao, appCtx.getBean(DaoConfig.class));
    // JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this,
    // systemDao,
    // appCtx.getBean(DaoConfig.class));
    metadata.setImplementationDescription("Da Vinci Drug Formulary Reference Server");
    setServerConformanceProvider(metadata);
    /*
     * ETag Support
     */
    setETagSupport(HapiProperties.getEtagSupport());
    /*
     * This server tries to dynamically generate narratives
     */
    FhirContext ctx = getFhirContext();
    ctx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator());
    /*
     * Default to JSON and pretty printing
     */
    setDefaultPrettyPrint(HapiProperties.getDefaultPrettyPrint());
    /*
     * Default encoding
     */
    setDefaultResponseEncoding(HapiProperties.getDefaultEncoding());
    /*
     * This configures the server to page search results to and from
     * the database, instead of only paging them to memory. This may mean
     * a performance hit when performing searches that return lots of results,
     * but makes the server much more scalable.
     */
    setPagingProvider(appCtx.getBean(DatabaseBackedPagingProvider.class));
    /*
     * This interceptor formats the output using nice colourful
     * HTML output when the request is detected to come from a
     * browser.
     */
    ResponseHighlighterInterceptor responseHighlighterInterceptor = new ResponseHighlighterInterceptor();
    this.registerInterceptor(responseHighlighterInterceptor);
    /*
     * Add Read Only Interceptor
     */
    ReadOnlyInterceptor readOnlyInterceptor = new ReadOnlyInterceptor();
    this.registerInterceptor(readOnlyInterceptor);
    /*
     * This interceptor handles the $export operation
     */
    ExportInterceptor exportInterceptor = new ExportInterceptor();
    this.registerInterceptor(exportInterceptor);
    /*
     * Add some logging for each request
     */
    LoggingInterceptor loggingInterceptor = new LoggingInterceptor();
    loggingInterceptor.setLoggerName(HapiProperties.getLoggerName());
    loggingInterceptor.setMessageFormat(HapiProperties.getLoggerFormat());
    loggingInterceptor.setErrorMessageFormat(HapiProperties.getLoggerErrorFormat());
    loggingInterceptor.setLogExceptions(HapiProperties.getLoggerLogExceptions());
    this.registerInterceptor(loggingInterceptor);
    /*
     * Add Authorization interceptor
     */
    PatientAuthorizationInterceptor authorizationInterceptor = new PatientAuthorizationInterceptor();
    this.registerInterceptor(authorizationInterceptor);
    /*
     * If you are hosting this server at a specific DNS name, the server will try to
     * figure out the FHIR base URL based on what the web container tells it, but
     * this doesn't always work. If you are setting links in your search bundles
     * that
     * just refer to "localhost", you might want to use a server address strategy:
     */
    String serverAddress = HapiProperties.getServerAddress();
    if (serverAddress != null && serverAddress.length() > 0) {
        setServerAddressStrategy(new HardcodedServerAddressStrategy(serverAddress));
    }
    /*
     * If you are using DSTU3+, you may want to add a terminology uploader, which
     * allows
     * uploading of external terminologies such as Snomed CT. Note that this
     * uploader
     * does not have any security attached (any anonymous user may use it by
     * default)
     * so it is a potential security vulnerability. Consider using an
     * AuthorizationInterceptor
     * with this feature.
     */
    if (false) {
        // <-- DISABLED RIGHT NOW
        registerProvider(appCtx.getBean(TerminologyUploaderProvider.class));
    }
    // manual triggering of a subscription delivery, enable this provider
    if (false) {
        // <-- DISABLED RIGHT NOW
        SubscriptionTriggeringProvider retriggeringProvider = appCtx.getBean(SubscriptionTriggeringProvider.class);
        registerProvider(retriggeringProvider);
    }
    // to your specific needs
    if (HapiProperties.getCorsEnabled()) {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedHeader(HttpHeaders.ORIGIN);
        config.addAllowedHeader(HttpHeaders.ACCEPT);
        config.addAllowedHeader(HttpHeaders.CONTENT_TYPE);
        config.addAllowedHeader(HttpHeaders.AUTHORIZATION);
        config.addAllowedHeader(HttpHeaders.CACHE_CONTROL);
        config.addAllowedHeader("x-fhir-starter");
        config.addAllowedHeader("X-Requested-With");
        config.addAllowedHeader("Prefer");
        String allAllowedCORSOrigins = HapiProperties.getCorsAllowedOrigin();
        Arrays.stream(allAllowedCORSOrigins.split(",")).forEach(o -> {
            config.addAllowedOrigin(o);
        });
        config.addAllowedOrigin(HapiProperties.getCorsAllowedOrigin());
        config.addExposedHeader("Location");
        config.addExposedHeader("Content-Location");
        config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH", "HEAD"));
        config.setAllowCredentials(HapiProperties.getCorsAllowedCredentials());
        // Create the interceptor and register it
        CorsInterceptor interceptor = new CorsInterceptor(config);
        registerInterceptor(interceptor);
    }
    // will activate them and match results against them
    if (HapiProperties.getSubscriptionWebsocketEnabled() || HapiProperties.getSubscriptionEmailEnabled() || HapiProperties.getSubscriptionRestHookEnabled()) {
        // Loads subscription interceptors (SubscriptionActivatingInterceptor,
        // SubscriptionMatcherInterceptor)
        // with activation of scheduled subscription
        SubscriptionInterceptorLoader subscriptionInterceptorLoader = appCtx.getBean(SubscriptionInterceptorLoader.class);
        subscriptionInterceptorLoader.registerInterceptors();
        // Subscription debug logging
        IInterceptorService interceptorService = appCtx.getBean(IInterceptorService.class);
        interceptorService.registerInterceptor(new SubscriptionDebugLogInterceptor());
    }
    // Cascading deletes
    DaoRegistry daoRegistry = appCtx.getBean(DaoRegistry.class);
    IInterceptorBroadcaster interceptorBroadcaster = appCtx.getBean(IInterceptorBroadcaster.class);
    if (HapiProperties.getAllowCascadingDeletes()) {
        CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(daoRegistry, interceptorBroadcaster);
        getInterceptorService().registerInterceptor(cascadingDeleteInterceptor);
    }
    // Binary Storage
    if (HapiProperties.isBinaryStorageEnabled()) {
        BinaryStorageInterceptor binaryStorageInterceptor = appCtx.getBean(BinaryStorageInterceptor.class);
        getInterceptorService().registerInterceptor(binaryStorageInterceptor);
    }
    // Validation
    IValidatorModule validatorModule;
    switch(fhirVersion) {
        case DSTU2:
            validatorModule = appCtx.getBean("myInstanceValidatorDstu2", IValidatorModule.class);
            break;
        case DSTU3:
            validatorModule = appCtx.getBean("myInstanceValidatorDstu3", IValidatorModule.class);
            break;
        case R4:
            validatorModule = appCtx.getBean("myInstanceValidatorR4", IValidatorModule.class);
            break;
        case R5:
            validatorModule = appCtx.getBean("myInstanceValidatorR5", IValidatorModule.class);
            break;
        // These versions are not supported by HAPI FHIR JPA
        case DSTU2_HL7ORG:
        case DSTU2_1:
        default:
            validatorModule = null;
            break;
    }
    if (validatorModule != null) {
        if (HapiProperties.getValidateRequestsEnabled()) {
            RequestValidatingInterceptor interceptor = new RequestValidatingInterceptor();
            interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
            interceptor.setValidatorModules(Collections.singletonList(validatorModule));
            registerInterceptor(interceptor);
        }
        if (HapiProperties.getValidateResponsesEnabled()) {
            ResponseValidatingInterceptor interceptor = new ResponseValidatingInterceptor();
            interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
            interceptor.setValidatorModules(Collections.singletonList(validatorModule));
            registerInterceptor(interceptor);
        }
    }
    // GraphQL
    if (HapiProperties.getGraphqlEnabled()) {
        if (fhirVersion.isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {
            registerProvider(appCtx.getBean(GraphQLProvider.class));
        }
    }
    if (!HapiProperties.getAllowedBundleTypes().isEmpty()) {
        String allowedBundleTypesString = HapiProperties.getAllowedBundleTypes();
        Set<String> allowedBundleTypes = new HashSet<>();
        Arrays.stream(allowedBundleTypesString.split(",")).forEach(o -> {
            BundleType type = BundleType.valueOf(o);
            allowedBundleTypes.add(type.toCode());
        });
        DaoConfig config = appCtx.getBean(DaoConfig.class);
        config.setBundleTypesAllowedForStorage(Collections.unmodifiableSet(new TreeSet<>(allowedBundleTypes)));
    }
    // Bulk Export
    if (HapiProperties.getBulkExportEnabled()) {
        registerProvider(appCtx.getBean(BulkDataExportProvider.class));
    }
}
Also used : Meta(org.hl7.fhir.dstu3.model.Meta) FhirContext(ca.uhn.fhir.context.FhirContext) ResourceProviderFactory(ca.uhn.fhir.jpa.util.ResourceProviderFactory) SubscriptionDebugLogInterceptor(ca.uhn.fhir.jpa.subscription.module.interceptor.SubscriptionDebugLogInterceptor) BinaryStorageInterceptor(ca.uhn.fhir.jpa.binstore.BinaryStorageInterceptor) FhirVersionEnum(ca.uhn.fhir.context.FhirVersionEnum) SubscriptionTriggeringProvider(ca.uhn.fhir.jpa.provider.SubscriptionTriggeringProvider) IInterceptorBroadcaster(ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster) JpaSystemProviderR4(ca.uhn.fhir.jpa.provider.r4.JpaSystemProviderR4) CorsInterceptor(ca.uhn.fhir.rest.server.interceptor.CorsInterceptor) ReadOnlyInterceptor(ca.uhn.fhir.jpa.starter.ReadOnlyInterceptor) ApplicationContext(org.springframework.context.ApplicationContext) BundleType(org.hl7.fhir.r4.model.Bundle.BundleType) ResponseHighlighterInterceptor(ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor) IValidatorModule(ca.uhn.fhir.validation.IValidatorModule) TreeSet(java.util.TreeSet) DefaultThymeleafNarrativeGenerator(ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator) TerminologyUploaderProvider(ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider) RequestValidatingInterceptor(ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor) HashSet(java.util.HashSet) BulkDataExportProvider(ca.uhn.fhir.jpa.bulk.BulkDataExportProvider) DaoConfig(ca.uhn.fhir.jpa.dao.DaoConfig) LoggingInterceptor(ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor) Bundle(org.hl7.fhir.dstu3.model.Bundle) IInterceptorService(ca.uhn.fhir.interceptor.api.IInterceptorService) DatabaseBackedPagingProvider(ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider) CascadingDeleteInterceptor(ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor) GraphQLProvider(ca.uhn.fhir.jpa.provider.GraphQLProvider) JpaSystemProviderDstu2(ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2) ResponseValidatingInterceptor(ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor) SubscriptionInterceptorLoader(ca.uhn.fhir.jpa.subscription.SubscriptionInterceptorLoader) CorsConfiguration(org.springframework.web.cors.CorsConfiguration) MetadataProvider(ca.uhn.fhir.jpa.starter.MetadataProvider) DaoRegistry(ca.uhn.fhir.jpa.dao.DaoRegistry) HardcodedServerAddressStrategy(ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy)

Example 2 with Subscription

use of org.hl7.fhir.r4.model.Subscription in project drug-formulary-ri by HL7-DaVinci.

the class ExampleServerDstu3IT method testWebsocketSubscription.

@Test
public void testWebsocketSubscription() throws Exception {
    /*
		 * Create subscription
		 */
    Subscription subscription = new Subscription();
    subscription.setReason("Monitor new neonatal function (note, age will be determined by the monitor)");
    subscription.setStatus(Subscription.SubscriptionStatus.REQUESTED);
    subscription.setCriteria("Observation?status=final");
    Subscription.SubscriptionChannelComponent channel = new Subscription.SubscriptionChannelComponent();
    channel.setType(Subscription.SubscriptionChannelType.WEBSOCKET);
    channel.setPayload("application/json");
    subscription.setChannel(channel);
    MethodOutcome methodOutcome = ourClient.create().resource(subscription).execute();
    IIdType mySubscriptionId = methodOutcome.getId();
    // Wait for the subscription to be activated
    waitForSize(1, () -> ourClient.search().forResource(Subscription.class).where(Subscription.STATUS.exactly().code("active")).cacheControl(new CacheControlDirective().setNoCache(true)).returnBundle(Bundle.class).execute().getEntry().size());
    /*
		 * Attach websocket
		 */
    WebSocketClient myWebSocketClient = new WebSocketClient();
    SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON);
    myWebSocketClient.start();
    URI echoUri = new URI("ws://localhost:" + ourPort + "/hapi-fhir-jpaserver/websocket");
    ClientUpgradeRequest request = new ClientUpgradeRequest();
    ourLog.info("Connecting to : {}", echoUri);
    Future<Session> connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request);
    Session session = connection.get(2, TimeUnit.SECONDS);
    ourLog.info("Connected to WS: {}", session.isOpen());
    /*
		 * Create a matching resource
		 */
    Observation obs = new Observation();
    obs.setStatus(Observation.ObservationStatus.FINAL);
    ourClient.create().resource(obs).execute();
    // Give some time for the subscription to deliver
    Thread.sleep(2000);
    /*
		 * Ensure that we receive a ping on the websocket
		 */
    waitForSize(1, () -> mySocketImplementation.myPingCount);
    /*
		 * Clean up
		 */
    ourClient.delete().resourceById(mySubscriptionId).execute();
}
Also used : CacheControlDirective(ca.uhn.fhir.rest.api.CacheControlDirective) WebSocketClient(org.eclipse.jetty.websocket.client.WebSocketClient) MethodOutcome(ca.uhn.fhir.rest.api.MethodOutcome) URI(java.net.URI) Observation(org.hl7.fhir.dstu3.model.Observation) ClientUpgradeRequest(org.eclipse.jetty.websocket.client.ClientUpgradeRequest) Subscription(org.hl7.fhir.dstu3.model.Subscription) IIdType(org.hl7.fhir.instance.model.api.IIdType) Session(org.eclipse.jetty.websocket.api.Session) Test(org.junit.Test)

Example 3 with Subscription

use of org.hl7.fhir.r4.model.Subscription in project org.hl7.fhir.core by hapifhir.

the class RdfParser method composeSubscriptionSubscriptionChannelComponent.

protected void composeSubscriptionSubscriptionChannelComponent(Complex parent, String parentType, String name, Subscription.SubscriptionChannelComponent element, int index) {
    if (element == null)
        return;
    Complex t;
    if (Utilities.noString(parentType))
        t = parent;
    else {
        t = parent.predicate("fhir:" + parentType + '.' + name);
    }
    composeBackboneElement(t, "channel", name, element, index);
    if (element.hasTypeElement())
        composeEnum(t, "Subscription", "type", element.getTypeElement(), -1);
    if (element.hasEndpointElement())
        composeUri(t, "Subscription", "endpoint", element.getEndpointElement(), -1);
    if (element.hasPayloadElement())
        composeString(t, "Subscription", "payload", element.getPayloadElement(), -1);
    if (element.hasHeaderElement())
        composeString(t, "Subscription", "header", element.getHeaderElement(), -1);
}
Also used : Complex(org.hl7.fhir.dstu2016may.formats.RdfGenerator.Complex)

Example 4 with Subscription

use of org.hl7.fhir.r4.model.Subscription in project org.hl7.fhir.core by hapifhir.

the class RdfParser method composeSubscription.

protected void composeSubscription(Complex parent, String parentType, String name, Subscription element, int index) {
    if (element == null)
        return;
    Complex t;
    if (Utilities.noString(parentType))
        t = parent;
    else {
        t = parent.predicate("fhir:" + parentType + '.' + name);
    }
    composeDomainResource(t, "Subscription", name, element, index);
    if (element.hasStatusElement())
        composeEnum(t, "Subscription", "status", element.getStatusElement(), -1);
    for (int i = 0; i < element.getContact().size(); i++) composeContactPoint(t, "Subscription", "contact", element.getContact().get(i), i);
    if (element.hasEndElement())
        composeInstant(t, "Subscription", "end", element.getEndElement(), -1);
    if (element.hasReasonElement())
        composeString(t, "Subscription", "reason", element.getReasonElement(), -1);
    if (element.hasCriteriaElement())
        composeString(t, "Subscription", "criteria", element.getCriteriaElement(), -1);
    if (element.hasErrorElement())
        composeString(t, "Subscription", "error", element.getErrorElement(), -1);
    if (element.hasChannel())
        composeSubscriptionSubscriptionChannelComponent(t, "Subscription", "channel", element.getChannel(), -1);
}
Also used : Complex(org.hl7.fhir.r4.utils.formats.Turtle.Complex)

Example 5 with Subscription

use of org.hl7.fhir.r4.model.Subscription in project org.hl7.fhir.core by hapifhir.

the class RdfParser method composeSubscriptionSubscriptionChannelComponent.

protected void composeSubscriptionSubscriptionChannelComponent(Complex parent, String parentType, String name, Subscription.SubscriptionChannelComponent element, int index) {
    if (element == null)
        return;
    Complex t;
    if (Utilities.noString(parentType))
        t = parent;
    else {
        t = parent.predicate("fhir:" + parentType + '.' + name);
    }
    composeBackboneElement(t, "channel", name, element, index);
    if (element.hasTypeElement())
        composeEnum(t, "Subscription", "type", element.getTypeElement(), -1);
    if (element.hasEndpointElement())
        composeUrl(t, "Subscription", "endpoint", element.getEndpointElement(), -1);
    if (element.hasPayloadElement())
        composeCode(t, "Subscription", "payload", element.getPayloadElement(), -1);
    for (int i = 0; i < element.getHeader().size(); i++) composeString(t, "Subscription", "header", element.getHeader().get(i), i);
}
Also used : Complex(org.hl7.fhir.r4.utils.formats.Turtle.Complex)

Aggregations

Subscription (com.ibm.cloud.eventnotifications.event_notifications.v1.model.Subscription)7 MethodOutcome (ca.uhn.fhir.rest.api.MethodOutcome)6 URI (java.net.URI)6 Session (org.eclipse.jetty.websocket.api.Session)6 ClientUpgradeRequest (org.eclipse.jetty.websocket.client.ClientUpgradeRequest)6 WebSocketClient (org.eclipse.jetty.websocket.client.WebSocketClient)6 IIdType (org.hl7.fhir.instance.model.api.IIdType)6 Test (org.junit.jupiter.api.Test)5 CacheControlDirective (ca.uhn.fhir.rest.api.CacheControlDirective)4 Test (org.testng.annotations.Test)4 RequestBuilder (com.ibm.cloud.sdk.core.http.RequestBuilder)3 HashMap (java.util.HashMap)3 MockResponse (okhttp3.mockwebserver.MockResponse)3 RecordedRequest (okhttp3.mockwebserver.RecordedRequest)3 PrepareForTest (org.powermock.core.classloader.annotations.PrepareForTest)3 FhirContext (ca.uhn.fhir.context.FhirContext)2 FhirVersionEnum (ca.uhn.fhir.context.FhirVersionEnum)2 CascadingDeleteInterceptor (ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor)2 DefaultThymeleafNarrativeGenerator (ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator)2 JsonObject (com.google.gson.JsonObject)2