Introduktion

Formål

Dette dokument er en vejledning til anvendelse af den Nationale Afprøvningsplatform (NAP). 

På baggrund af dette dokument, er det muligt for leverandører af både lægepraksissystemer (LPS) og afprøvningsprojekter, at udvikle systemer som integrerer med NAP. 

Sammenhæng med øvrige dokumenter

Dette dokument er en del af den samlede dokumentation for NAP Platformen.

Dokumentet er udformet, så det i videst muligt omfang opfylder sit formål uafhængigt af de øvrige dokumenter.

Ønskes mere information omkring arkitektur og design findes dette på NAP Platform - Design og Arkitektur beskrivelse.

Ønskes mere information omkring installationsvejledning til anvender kan findes på NAP Platform - Installationsvejledning.


Kom i gang med NAP som projektudvikler

I følgende beskrives opsætningstrinene for at komme i gang med NAP platformen, hvis man vil oprette et nyt projekt som skal ind i NAP'en. 

Denne guide er til opsætning af et lokalt miljø. 


Krav til software:

Docker (Docker Engine version 18.02.0+) skal være installeret, da opsætningen foregår via docker-compose.

For at alle komponenterne skal virke, skal nap-compose køre som en reverse proxy.

Et docker netværk kaldet nap_net skal laves "docker network create nap_net".

Nedenstående komponenter skal hentes fra https://svn.nspop.dk/svn/components/nap/.

Nap-host-java

Start med at hente nap-host-java I den executable der skal bruges.

Windows

Mac OS X

Linux


Når nap-host-java åbnes, vil der blive præsenteret en login dialog.  

Login ved at trykke på localhost og bruge default login credentials. Dette vil trække en SAMLAssertion fra STS på test1, som kan bruges i 30 min. Når der er brugt et gyldigt login, vil man se et eksempel på et værtssystem. 

Applikationen viser 4 faner, hvor 3 af dem har screenshots som billeder (for at simulere et værtssytem), men den sidste fane "Afprøvningsløsning", indeholder nap-lobby-web, som viser de tilgængelig projekter.


Indtast et cpr nummer på en test person (Eksempelvis "2708599967", som er et hyppigt anvendt test cpr nummer), herefter kan der browses rundt i fanerne.

For at fanen "afprøvningsplatformen" kan fungere, skal nap-compose og nap-lobby-web startes, som er de næste trin i denne opsætning.

Nap-Compose

Ideen med nap-compose er at opsætte en reverse proxy, som skal fungerer som en NSP loadbalancer med path rewriting.

For at starte denne reverse proxy køres "docker-compose up". Dette vil åbne port 8080 på localhost.

nap-compose på SVN

Nap-Lobby-web

Nap-lobby-web er kataloget for de afprøvningsprojekter, der findes i NAP.

Kør "docker-compose up"  fra compose/development og den er derefter tilgængelig for nap-host-java, da den vil hoste lobbyen på http://localhost:8080/nap/lobby/web/, som er den url nap-host-java kigger efter. 

For at nap-lobby-web skal vise nogen projekter, skal den have forbindelse til nap-administration.

nap-lobby-web på SVN

Nap-administration

Nap-administration er backenden og database, hvor projekterne bliver gemt.

Kør "docker-compose up" fra compose/development og den er derefter tilgængelig for nap-lobby-web og projekterne bliver herefter vist.

nap-administration på SVN

Ny implementering / Dit projekt

Der ligger et udviklingsprojekt som hedder "Developer", som der hurtigt kan sætte gang i anvendelsen af NAP platformen som udviklingsmiljø.

Hvis dette projekt trykkes på, vil nap-java-host åbne en hvilken som helst applikation der hostes på http://localhost:4600.

Du kan læse mere om, hvordan der sendes beskeder til og fra et værtssystem på NAP SDK - Guide til anvendere.

Konfigurer din løsning ind i NAP

Når en nyt projekt skal fungere med NAP Platformen, er der 2 steder, hvor platformen lokalt skal konfigureres.

Reverse proxy

Reverse proxy konfigureres ved at opdatere nap-httpd.conf. i nap-compose.

<VirtualHost *:8080> ServerName nap

ProxyPass /nap/reference/web/services/main http://napreffacade:8080

ProxyPassReverse /nap/reference/web/services/main http://napreffacade:8080

ProxyPass /nap/reference/web http://naprefweb:8080

ProxyPassReverse /nap/reference/web http://naprefweb:8080

</VirtualHost>

Lav en konfiguration magen til ovenfor hvor reference og naprefweb udskiftes efter ønske med navnene på dine docker-services.

Urlen skal passe med, den url der indsættes i databasen nedenfor.

Database

For at dit projekt skal vises i lobbyen, skal projektet optræde i din lokale database.  

Du kan gøre dette med sql inserts direkte eller opdatere compose/db/migration/V2__insert_data_localhost.sql med en kopi af nedenstående, som bare opdateres med dit nye info

insert into administration.Project (active, description, releaseDate, version, name, id) values (true, 'Dit udviklingsprojekt kan åbnes her.', '2018-11-30', '1.0.0', 'Nap Web Develop',  UuidToBin(UUID()));
insert into administration.Manifest (releaseDate, url, version, id) values ('2019-11-30', 'http://localhost:8080/nap/developer/web/', '1.0.0', UuidToBin(UUID()));
insert into WebApp (active, manifest_id, name, id, project_id) values (true, (select id from administration.Manifest where url LIKE 'http://localhost:8080/nap/developer/web/' ), 'Nap Web Developer version 0.0.1', UuidToBin(UUID()), (select id from administration.Project where name LIKE 'Nap Web Develop'));
insert into WebApp_cvr (WebApp_id, cvr) values ((select id from administration.WebApp where name LIKE 'Nap Web Developer version 0.0.1'), '20921897');
insert into Manifest_eventCatalogueVersions (Manifest_id, eventCatalogueVersions) values ((select id from administration.Manifest where url LIKE 'http://localhost:8080/nap/developer/web/' ), 1);

For at ændringer bliver reflekteret, skal databasen og flyway genstartes, og dette gøres med "docker-compose down & docker-compose up". 

Kom igang med NAP som værtssystem-/ LPS udvikler

I det følgende beskrives, hvordan man som værtssystem-/ LPS udvikler, skal integrerer NAP platformen ind i det respektive system. 

Integrationen med NAP

For at kommunikere med NAP'en, skal det givne værtssystem/LPS opsættes, således den kan lytte på specifikke beskeder fra SDK'et. 

I det nedenstående vil eksemplerne tage udgangspunkt i JavaFX, og der kan derfor også tages udgangspunkt i nap-host-java, hvis der er brug for inspiration.

nap-java-host på SVN.

Opsætning af kommunikation med SDK.

For at kunne kommunikere med SDK'et, gøres brug af et Webview, som er et JavaFX komponent. Webviewet kan indlæse hjemmesider, samt der er mulighedhed for at indlejre javascript på den indlæste HTML side.

Det er vigtigt, at det er mulighed for at indlejre javascript i Webviewet, da det er den måde SDK'et fungere på. 

Læs mere om dette her NAP SDK - Guide til udviklere.

I nedenstående eksempel, tilføjes "NAPBridge" i variablen "NAP" på window, som er i global scope på den indlæste HTML side.

final JSObject window = (JSObject) webEngine.executeScript("window");
window.setMember("NAP", napBridge)


En implementering af NAP Bridge kan se således ud:

public class NAPBridge {
        private JSObject bridge;

        /**
         * Transforming a JSON string into a NAPMessage and sending it to subscribers.
         * @param rawEventString
         */
        public void send(String rawEventString) {
            try {
                System.out.println(this.getClass().getName() + " send(): " + rawEventString);
                NAPMessage msg = objectMapper.readValue(rawEventString, NAPMessage.class);
                notifyListeners(msg);
            } catch (IOException ioException) {
                System.out.println(this.getClass().getName() + " " + ioException);
            }
        }

        /**
         * Sets the bridge to act as a callback.
         * @param bridge
         */
        public void setCallback(JSObject bridge) {
            System.out.println(this.getClass().getName() + " setCallBack(): " +  bridge);
            this.bridge = bridge;
        }
   }
}

Et JS objekt, som bridge variablen, gør at man kan eksekvere javascript metoder og undersøge javascript properties. 

Der er implementeret to metoder, som er send() og setCallback(), det er disse to metoder som SDK'et wrapper og kalder. 


Send(), er et håndtag til at sende beskeder til hosten, gør brug af et internt subscribe pattern, som notificere dem som lytter. En implementering af dem der lytter, kunne se således ud:

private void handleBridgeCallBacks(NAPMessage napMessage) {
        System.out.println("Bridge got type NAPMessageType" + napMessage.getEvent().getNAPEventType());
        switch (napMessage.getEvent().getNAPEventType()) {
            case WebAppOpen:
                try {
                    WebApp webApp = this.getWebAppById(
                            Configuration.getInstance().getNapAdminUrl(this.environment),
                            FHIRResoureValueGetter.getWebAppId(napMessage),
                            this.base64EncodedSAMLToken
                    );
                    if (webApp != null) {
                        Platform.runLater(() -> this.webAppPane.openURL(webApp.getManifest().getUrl()));
                    }
                } catch (ConnectException e) {
                    System.err.println("Kunne ikke oprette forbindelse til serveren");
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
            case PatientOpen:
                sendCurrentPatient(txfCPR.getText(), napMessage.getDate(), napMessage.getId());
                break;
            case SessionOpen:
                sendToken(napMessage);
                break;
            case SessionClose:
                sendSessionClosed(napMessage);
                break;
            case SessionError:
                sendSessionError(napMessage);
        }
    }
}


Når der skal sendes en NAP besked, kan der så gøres brug af bridgen. Call() tager imod en string, som angiver hvilken metode man vil kalde, her "handle", da det er den variable som SDK'et lytter på. Metoden sender en string, hvori indholdet repræsentere en JSON struktur med indholdet af en NAPMessage.

 if(napBridge.bridge != null) {
     this.napBridge.bridge.call("handle", eventRawJSONString);
 }

NAP Lobby Web

Når kommunikationen er opsat med SDK'erne, eller initialt blot implementering af NapSessionOpen (NAP SDK - Guide til anvendere#Guidetilanvendere-Session-open/Session-close), er det nu klart til at vise alle de projekter der er tildelt.

De forskellige typer events kan læses på NAP SDK - Guide til anvendere.

For at se de projekter der er tilgængelige, skal NAP Lobby Web hentes i det nuværende system.

Dette gøres ved at få WebView'et til at indlæse en af nedenstående URL'er til nap-lobby-web.

Test1: INDSÆT URL

Test2: INDSÆT URL

Produktion: INDSÆT URL

NAP Test Web

Projektet har til hensigt at teste, at der kan sendes og modtages beskender igennem NAP SDK'erne.

Der er separate tests cases, som kan køres enkeltvis eller samlet. Den er derfor oplagt til at teste et værksystems implementering af eventkataloget.

Dette afprøvningsprojekt ligger både på test1 og test2 og kan åbnes fra lobbyen i det givne miljø.

Når et projekt i lobbyen klikkes sendes et WebAppOpen event:

 /**
   * Send and open-webapp event to over the host bridge
   * @param webAppId the wep app id open
   */
  public instructHostToOpenWebApp(webAppId: string): void {
    const napMsg: NAPMessage = {
      date: new Date().toISOString(),
      id: UUID(),
      event: {
        type: NAPEventCatalogue.v1.WebAppOpen,
        context: [
          {
            resource: {
              resourceType: FHIRValueSetter.FHIRResourceType.Basic,
              code: {
                coding: [
                  {
                    code: NAPEventCatalogue.v1.WebAppOpen,
                    system: FHIRValueSetter.FHIRSystem.NAP,
                  },
                ],
              },
              identifier: [
                { system: FHIRValueSetter.FHIRSystem.NAP, value: webAppId },
              ],
            },
          },
        ],
      },
    };
    this.napSDK.sendMessage(napMsg);
  }

Et eksempel kunne være: 

{
 "date":"2020-06-22T10:40:50.079Z",
 "id":"43f642ed-b7ca-4c5b-91fc-e7fdf6e8ee4c",
 "event":{
	"type":"nap-open-webApp",
	"context":[{
		"resource":{
			"resourceType":"Basic",
			"code":{
				"coding":[{
					"code":"nap-open-webApp",
					"system":"nap"
				}]
			},
			"identifier":[{
				"system":"nap",
				"value":"11eaac74-505d-9772-ac11-0242c0a87002"
			}]
		}
 	}]
 }
}

Webappen med det givne id, kan så efterfølgende hentes på adminurl/webapp/id på hosten og åbnes i den indlejrede browser.

Test1: INDSÆT URL

Test2: INDSÆT URL

Produktion: INDSÆT URL