Mirth

Page last edited 485 giorni 0 ore fa
Da wiki.betaingegneria.it.

Indice

Mirth Connect[modifica]

Generalità[modifica]

Una piattaforma per l'installazione e l'esecuzione di web services, e il collegamento con basi dati in lettura/scrittura, che parla nativamente il linguaggio HL7.

Installazione di Mirth Connect[modifica]

Prerequisito: installazione della JVM[modifica]

L'installazione non partirà nemmeno se l'installer non avvertirà la presenza di Sun JDK. Ho provato anche con OpenJDK, ma non c'è verso.

Nel nuovo OS Ubuntu 12.04 ho installato la Java Virtual Machine come descritto in Java#Nuovo_OS Quando si avvia l'interfaccia di comunicazione con Mirth, selezionare:

 Altro > immettere /usr/local/lib/jre1.7.0_04/bin/javaws

e dare INVIO

Prerequisito: installazione del driver JDBC Oracle[modifica]

Scaricare un driver jdbc che si vuole dal sito dell'Oracle. Io ad esempio ho scaricato l'Oracle Thin Client per Oracle 10.2 e all'interno c'era già il file ojdbc14.jar.

Nella mia installazione il file con la libreria Java jdbc l'ho messo in

 /opt/oracle/instantclient_10_2

dove si trovano anche i tnsnames; questo percorso va inserito nella variabile di ambiente CLASSPATH:

  $ CLASSPATH=/opt/oracle/instantclient_10_2

Istruzioni per Centos, Redhat o Fedora[modifica]

Installando i pacchetti rpm di oracle instant client in una distribuzione Centos, Redhat o Fedora i files vengono installati in

   /usr/lib/oracle/<ver>/client/

oppure in

   /usr/lib/oracle/<ver>/client64/

a seconda se si installano i pacchetti a 32 o 64 bit.

Quindi non viene in ogni caso installato nulla in /usr/lib64, nemmeno nel caso di pacchetti a 64 bit.

Come evitare l'errore oracle: ORA-01882: timezone region not found[modifica]

Tale errore si può presentare in alcune installazioni di Oracle per le quali manca il nome del Timezone che java utilizza prendendolo dal sistema. In particolare se il comando sql seguente:

   SELECT DISTINCT TZNAME FROM V$TIMEZONE_NAMES;

Non da, ad esempio alcuna riga con TZNAME = 'Europe/Rome', allora il comando sql:

   ALTER DATABASE SET TIME_ZONE ='Europe/Rome';

da come errore:

   ERROR at line 1:
   ORA-01882: timezone region  not found

Che è lo stesso errore che si verifica quando ci si connette al database con una libreria jdbc precedente a ojdbc14. Per evitare tale errore occorre evitare che MirthConnect usi una versione vecchia della libreria jdbc, che si trova tra i drivers del pacchetto di installazione, occorre cancellarla. La versione di MirthConnect in mio possesso conteneva la libreria ojdb v.6.12.1.0.2 nel file:

   /opt/mirthconnect/server-lib/database/ojdbc6-12.1.0.2.jar.

La versione che ho scaricato con instantclient è ojdbc v.14 contenuta nel file:

   /usr/lib/oracle/11.2/client64/lib/ojdbc14.jar

In definitiva i comandi da dare dopo l'installazione degli rpm di oracle instant client v. 11.2 e della libreria jdbc relativa e dopo l'installazione di Mirth, i cui dettagli sono spiegati appresso, sono i seguenti:

   $ sudo rm /opt/mirthconnect/server-lib/database/ojdbc6-12.1.0.2.jar
   $ sudo cp /usr/lib/oracle/11.2/client64/lib/ojdbc14.jar /opt/mirthconnect/server-lib/database/

La sostituzione della versione della libreria è necessaria per evitare l'errore seguente che si verifica alla connessione con un database oracle:

   java.sql.SQLException: ORA-00604: error occurred at recursive SQL level 1
   ORA-01882: timezone region  not found

Tale bug si presenta con le versioni precedenti a ojdbc14.

Nota bene[modifica]

Il client Oracle serve affinché i servizi possano interagire con un DB relazionale.

Anche Mirth stesso scrive le sue configurazioni in un database, e si può configurare una serie di db relazionali molto usati: MySQL, PostGRES, Oracle affiché esso salvi tutti i parametri per il suo funzionamento.

Mirth "out-of-the-box" utilizza un Db con poche pretese, giusto per valutare il prodotto: Apache Derby.

Istruzioni per l'installazione di Mirth[modifica]

Scaricare il paccozzo mirth-1.8.2.4472.1351-linux-installer.bin dal sito Mirth Corporation. è la versione 1.8.2.

Il download può durare un pochino, sono 85 MB. Al termine portarsi nella direcory di download e

 $ sudo -s
 # chmod +x mirth-1.8.2.4472.1351-linux-installer.bin
 # mkdir /opt/Mirth
 # chown marcob:marcob /opt/Mirth
 # ^D
 $ ./mirth-1.8.2.4472.1351-linux-installer.bin [INVIO]

L'installazione ci mette un pochino. Alla fine, punto il browser su http://localhost:8080/, compare la pagina seguente:

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Cliccare sul pulsante verde. A questo punto potrebbe presentarsi un problema: è descritto qui assieme alla sua soluzione.

Attenzione![modifica]

Questo dopo l'installazione. Ma nelle volte successive, occorre

  1. lanciare Mirth a mano
 $ cd /opt/Mirth
 $ mirth<invio>
  1. puntare il browser nella Mirth Home Page
  2. cliccare sul pulsante verde, compare la login
Installazione del servizio per Fedora, Centos e Redhat[modifica]

Per installare Mirth Connect come servizio che viene lanciato automaticamente all'avvio occorre eseguire i seguenti comandi:

   $ sudo cp /opt/mirthconnect/mcservice /etc/init.d
   $ sudo chkconfig --add mcservice
   $ sudo chkconfig mcservice on
   $ service mcservice start

Nelle ultime versioni di Fedora si possono usare anche i seguenti comandi:

   $ sudo cp /opt/mirthconnect/mcservice /etc/init.d
   $ sudo systemctl enable mcservice.service
   $ sudo systemctl start mcservice.service

Login[modifica]

Se il problema non c'è o è stato risolto, appare la maschera di login:

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

digitare user = pass = admin

Mirth all'opera[modifica]

Primo accesso[modifica]

Viene subito chiesto di cambiare (si è obbligati!) la password di amministratore (di default è sempre admin/admin)

Dashboard (cruscotto)[modifica]

Il cruscotto raccoglie informazioni e controlli sui principali oggetti di Mirth che sono i Canali.

Un canale è un insieme di funzioni che generalmente costituiscono una applicazione completa.

Una canale è un'operazione composta. Ad esempio

  • lettura database
  • costruzione busta XML con il messaggio
  • invio della busta al web service in ascolto
  • processo del messaggio ritorno (update database con il risultato della invocazione del WS remoto)

Ma il processo può anche essere rovesciato e cominicare con l'ascolto da un servizio per poi scrivere su database.

Channels (Canali)[modifica]

Cominciamo subito a creare un canale. Si tenga a mente che si fa sempre prima una lettura e poi una scrittura. In realtà accanto alla lettura ci può essere qualche scrittura di contorno ma il canale inizia sempre con un input e finisce con un output.

Cliccare sulla sinistra Channels nel menu Mirth Connect, in alto. Poi cliccare su New Channel nel menu Channel Tasks.

Compare la scheda Edit Channel nella quale compaiono 4 sotto schede:

  • Summary (nella quale scriviamo subito il nome del canale)
  • Source in cui descriveremo da dove e come il servizio legge i dati da spedire
  • Destinations in cui descriveremo dove deve andare il messaggio e
  • Scripts che è speciale (mi sembra serva a scrive il codice Java che incorpora i dati letti dalla Source dentro l'XML da sparare, in sostanza elaborazioni in itinere lungo il canale).
Source[modifica]

Nel tab Source possiamo definire ad esempio che i dati da spedire vengano letti da una tabella Oracle (ma nativamente possiamo farlo anche da MySQL, Postgres e SQL Server, o da un altro webservice).

Scelgo Oracle 10g Release 2 nel Driver. Poi per suggerire cosa devo scrivere, premo su Insert URL Template e scrivo

 jdbc:oracle:thin:@192.168.0.2:1521:XE

ho sostituito

  • host con 192.168.0.2 (ma in /etc/hosts avevo la riga
 192.168.0.2   bach

per cui ho sostituito host con bach)

  • port con 1521
  • database con XE
Errata[modifica]

per sapere cosa scrivere qui, fare riferimento al file $ORACLE_HOME/tns/tnsnames.ora in cui c'è il nome del database e la porta ed il nome del server. Nel mio caso

 BACH =
 (DESCRIPTION =
   (ADDRESS_LIST =
     (ADDRESS = (PROTOCOL = TCP)(HOST = bach)(PORT = 1521))
   )
   (CONNECT_DATA =
     (SID = XE)
   )
 )
Corrige[modifica]

NON si deve fare riferimento al TNS se si usa il thin client! Si usano le informazioni scritte dentro al tnsnames.ora ma in un altro modo. Esempio che calza meglio

 svil.mydomain.eu =
 (DESCRIPTION =
   (ADDRESS = (PROTOCOL = TCP)(HOST = dbsvila.mydomain.eu)(PORT = 1521))
   (CONNECT_DATA =
     (SID = svil)
   )
 )

Qui il nome del TNS è diverso dal nome fisico della macchina (questa particolarità nel precedente esempio mi aveva indotto in errore)

  • nome fisico: dbsvila.mydomain.eu
  • nome TNS: svil.mydomain.eu

se si usassero i client OCI la stringa di connessione sarebbe

 jdbc:oracle:oci:username/password@svil.mydomain.eu

ma dovendo usare il client THIN la stringa di connessione è

 jdbc:oracle:thin:@dbsvila.mydomain.eu:1521:svil

Il risultato è il seguente (premere il tasto Select):

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Questa finestra serve per costruire le query di selezione; ad esempio se scelgo AMMORTAMENTI (e il check si propasga di default a tutti i campi della tabella AMMORTAMENTI) la query che viene scritta è questa:

  SELECT 
     AMMORTAMENTI.ID AS AMMORTAMENTI_ID, 
     AMMORTAMENTI.DESCRIZ AS AMMORTAMENTI_DESCRIZ, 
     AMMORTAMENTI.AMMORTAMENTO AS AMMORTAMENTI_AMMORTAMENTO, 
     AMMORTAMENTI.ANNI AS AMMORTAMENTI_ANNI, 
     AMMORTAMENTI.FLAG_INV AS AMMORTAMENTI_FLAG_INV
  FROM 
     AMMORTAMENTI

Fare attenzione a non aggiungere il ; finale, che sarebbe considerato un errore che impedirebbe il corretto polling,

In caso di errore[modifica]

Se premo sul pulsante Select mi esce l'errore

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Nota che nel caso bach (in cui host fisico e tns hannno lo stesso nome) esce questo errore ma il connettore invece funziona...

Ora, sempre nella tab Source vado nella casella di testo SQL e digito la query che estrarrà i dati da incartare nell'XML e spedire (o salvare); nel mio esempio:

  select * from ricevute.ricevute

nello schema ricevute, c'è una tabella ricevute: le leggo tutte.

Non è finita! Occorre sempre definire un Transformer per ogni connettore. Nel Transformer si dice come si presentano i dati uscendo dal DB (Inbound) e come li consegno al servizio (Outbound).

L'XML di Outbound della Source diventa l'XML di inbound della Destination

Destinations[modifica]

Qui, dopo aver detto come leggere. diciamo come scrivere. La cosa più semplice è scrivere in un file i dati letti. Mirth li scriverà in un formato XML di default. Ad esempio potrà scrivere un testo del tipo:

 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
  <result>
   <id>103500</id>
   <iddipartimento>11</iddipartimento>
   <pagante>Giuseppe Garibaldi</pagante>
   2011-06-03
   <importo>12</importo>
   <idtipopagamento>1</idtipopagamento>
   <idstorno/>
   <idutente>285</idutente>
   <flag_storno>0</flag_storno>
   <numero>1</numero>
  </result>

Per fare questo dobbiamo

  • scegliere il Connector Type che in questo caso sarà File Writer;
  • poi scriviamo la Directory (es. /tmp/) e controlliamo se Mirth ci può scrivere dentro cliccando su Test Write;
  • scriviamo il file name (es. file.txt)
  • cosa dobbiamo scrivere dentro al file? abbiamo molte scelte sulla destra (Destination Mappings), io ho scelto Transformed Data (si fa Drag & Drop dentro la casellina Template) che in sostanza scrive i dati letti dalla tabella Oracle trasformati in XML.

Ora che ci penso, vado a vedere cosa c'è dentro a /tmp/file.txt:

 -rw-r--r-- 1 marcob marcob 500544 2011-06-16 16:59 /tmp/file.txt

Opssss... il file cresce è già a mezzo mega.

Ci credo! Ogni 5 secondi fa una scansione della tabella e scrive nel file (in append). Posso regolare l'intervallo di tempo tornando nella scheda Source e impostando Polling Frequency (ms) ad un valore più alto (c'è scritto 5000, metto 50000: sono millisecondi, quindi 5000 = 5 s).

Possiamo anche riscrivere ogni volta il file ex novo (invece di andare in append): scheda Destinations, radio button Append to File.

Destinazioni diverse da file locali[modifica]

La parte più interessante è la comunicazione con end point sul web.

  • Cliccare su New Destination
  • scegliere Connector Type = HTTP Sender
  • scrivere l'url dell'end-point (vedi articolo sui web services): sarà per me http://PROVAX00X00X000Y:Salve123@jsbach/inps/
  • sulla destra in basso, sulle Destination Mappings, si troveranno anche i campi estratti dalla Query SQL impostata nel Reader
  • Per tutti i campi che interessano, cliccare su New delle Reqeust Variables, scrivere il nome concordato nel WSDL dell'end point, e trascinare il nome dalla lista di sinistra dentro alla colonna di destra (Value).
  • se il campo è composto, usare i Transformed Data.

Insomma qui c'è ancora molto da imparare.

Usare SOAP sender[modifica]

Non so che differenza ci sia, ma con SOAP sembrerebbe più semplice. Bisogna caricare il file WSDL con la descrizione del servizio; caricato il file e premendo il pulsante Import Functions si ottiene l'elenco delle funzioni incluse nel servizio. A me non funziona, ma sembra così.

Esempio Umberto[modifica]

La Source ha la connessione jdbc, la query: tutto a posto, fin qui ci ero arrivato da solo

Nelle Destinations sono indicate tre destinazioni:

  • file: è la destinazione che per ogni invocazione del canale scrive i dati da spedire nel FS locale, come log
  • http: è l'invocazione del ws remoto: avviene con il metodo http_sender (non SOAP sender) ma ha questi dati:
<soapenv:Envelope 
        xmlns:inv="http://inviocertificatorequest.xsd.cert.mirsac.remotedomain.org" 
        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
        xmlns:tip="http://tipicert.xsd.cert.mirsac.remotedomain.org">
<soapenv:Header>
        <wsse:Security soapenv:mustUnderstand="0" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
          <wsu:Timestamp wsu:Id="Timestamp-1" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
             <wsu:Created>2011-06-15T10:32:18.681Z</wsu:Created>
             <wsu:Expires>2011-06-15T10:33:18.681Z</wsu:Expires>
          </wsu:Timestamp>
       </wsse:Security>
    </soapenv:Header>
    <soapenv:Body>
       <inv:InvioCertificato>
          <inv:medico>
             <!--Optional:
             <tip:codiceFiscale/>-->
             <!--Optional:-->
             <tip:pincode>1234567890</tip:pincode>
             <tip:codiceRegione>100</tip:codiceRegione>
             <tip:codiceAsl>102</tip:codiceAsl>
          </inv:medico>
          <inv:lavoratore>
             <tip:codiceFiscale>AAXAAA00A50H5L1O</tip:codiceFiscale>
          </inv:lavoratore>
          <inv:residenzaODomicilioAbituale>
             <tip:via>VIA DEI MULINI 12</tip:via>
             <tip:cap>36070</tip:cap>
             <!--Optional:-->
             <tip:codiceCatastale/>
             <!--Optional:-->
             <tip:comune/>
            <!--Optional:-->
             <tip:provincia/>
          </inv:residenzaODomicilioAbituale>
          <!--Optional:-->
          <inv:indirizzoDiReperibilita>
             <!--Optional:-->
             <tip:cognome/>
             <!--Optional:-->
             <tip:indirizzo>
                <tip:via>VIA DEI MULINI 12</tip:via>
                <tip:cap>36070</tip:cap>
                <!--Optional:-->
                <tip:codiceCatastale/>
                <!--Optional:-->
                <tip:comune/>
                <!--Optional:-->
                <tip:provincia/>
             </tip:indirizzo>
          </inv:indirizzoDiReperibilita>
          <inv:certificato>
             <tip:dataRilascio>2011-06-15</tip:dataRilascio>
             <tip:dataInizio>2011-06-15</tip:dataInizio>
             <tip:dataFine>2012-06-15</tip:dataFine>
             <tip:visita>A</tip:visita>
             <tip:tipoCertificato>I</tip:tipoCertificato>
             <!--Optional:-->
             <tip:codiceDiagnosi></tip:codiceDiagnosi>
             <!--Optional:-->
             <tip:noteDiagnosi></tip:noteDiagnosi>
          </inv:certificato>
       </inv:InvioCertificato>
    </soapenv:Body>
 </soapenv:Envelope>

Come generare questo tracciato XML? usando [1].

Per poter inserire i valori letti dal database all'interno dei segnaposto nel file xml di cui sopra è necessario che per ogni canale sia creato un Transformer:

    • da SoapUI chiamare il servizio a cui ci si vuole rivolgere
    • SoapUI ritornerà l'XML: copiarlo e incollarlo
    • Recuperare l'XML con cui viene prodotta la lettura del database (Source > Edit Transformer > Message Templates (nella scheda sulla destra))
  <?xml version="1.0" encoding="UTF-8" standalone="no"?>
   <result>
     <codfisc>value</codfisc>
     <pincode>value</pincode>
   </result>
    • incollarlo dentro a Destinations > Edit Transformer > Message Templates (nella scheda sulla destra)
    • cliccare su Add New Step, in variable scrivere codfisc
    • cliccare su Messag Tree sulla scheda destra, aprire l'albero e trascinare il valore dentro la casella Mapping
    • ripetere per tutte le altre variabili
    • Così facendo appariranno i nomi delle variabili sulla tab Destination Mappings nella pagina elenco delle Destinations
    • Trascinare le variabili dentro al valore del $payload come evidenziato nel frammento che segue (è il valore della variabile $payload):
 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:int="http://interrogazionelavoratorerequest.xsd.cert.mirsac.remotedomain.org">
   <soapenv:Header/>
   <soapenv:Body>
      <int:InterrogazioneLavoratore>
         <int:pincodeMedico>${pincode}</int:pincodeMedico>
         <int:codiceFiscale>${codfisc}</int:codiceFiscale>
      </int:InterrogazioneLavoratore>
   </soapenv:Body> 
 </soapenv:Envelope>
  • la terza destinazione (file_risultato) è la scrittura dei risultati della response in un file.

E alla fine: installazione del canale[modifica]

Ora, per "deployare" il servizio occorre

  • salvare (Channel Tasks > Save Changes)
  • Validare il connettore (Channel Tasks > Validate Connector)
  • cliccare su Mirth COnnect > Channels
  • Cliccare su Channel Tasks > Deploy All

il servizio parte! Se si torna al cruscotto, in basso sulla tab Server Log si dovrebbe leggere

  [2011-06-16 16:37:47,949]  INFO  (com.webreach.mirth.connectors.jdbc.JdbcMessageReceiver:356): Successfully connected to: jdbc://query

e se si clicca sulla tab Dashboard Status Panel si dovrebbe leggere un elenco di eventi che testimonia, ad esempio nel mio caso, la successione di eventi Source: Database reader (XML -> XML) e Destination: File writer -> Destination 1 con la data e l'ora dell'evento e le informazioni accessorie (ad esempio: Result written to: /tmp/file.txt)

Esempio più completo[modifica]

  1. Creo un canale InterrogaLavoratore che legge da Source=DB e scrive su Destination=HTTP Sender.
  2. Creo un secondo canale che dovrà ospitare la response (INPSResponse):
  • Source: Channel Reader
  • Destination: File writer: decidere un file su cui scrivere (es. /tmp/lavoratore_response.txt): Sulla destra (Destination Mappings) vedo le variabili
    • rispostaKO
    • tipoErrore
    • sezioneErrata
    • descrizione

che mi arrivano dal transformer: Se edito il Transformer non vedo nessun XML, nessuno step, come se le variabili fossero ereditate da qualche altra parte... Probabilmente, a posteriori, arrivano dal canale InterrogaLavoratore che scrive sul canale presente.


Nell'impostazione di Chiama WS INPS (che è una destinazione del canale) definisco che la Response debba essere inviata al canale (da creare) INPSResponse.

Canale INPSResponse[modifica]

Sta tutto a scrivere bene il Transformer con gli XML giusti. In particolare, in questo caso, usavo il messaggio XML

 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
  xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Header/>
  <soapenv:Body>
     <p600:RicevutaLavoratore xmlns:p600="http://interrogazionelavoratoreresponse.xsd.cert.mirsac.remotedomain.org">
        <p600:ricevutaNonOk>
           <p706:errore xmlns:p706="http://tipicert.xsd.cert.mirsac.remotedomain.org">
              <p706:tipoErrore>111</p706:tipoErrore>
              <p706:sezioneErrata>S111</p706:sezioneErrata>
              <p706:descrizione>Pincode assente o errato</p706:descrizione>
           </p706:errore>
        </p600:ricevutaNonOk>
     </p600:RicevutaLavoratore>
  </soapenv:Body>
 </soapenv:Envelope>

come Inbound, che è lo stesso ritornatomi dal SoapUI. Ma i prefissi per i nomi dei tag non piacciono a Mirth: la soluzione è: stripparli! Ottengo questo XML che metto in Inbound del Transformer:

 <Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
   xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
   xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Header/>
  <Body>
     <RicevutaLavoratore xmlns="http://interrogazionelavoratoreresponse.xsd.cert.mirsac.remotedomain.org">
        <ricevutaNonOk>
           <errore xmlns="http://tipicert.xsd.cert.mirsac.remotedomain.org">
              <tipoErrore>?</tipoErrore>
              <sezioneErrata>?</sezioneErrata>
              <descrizione>?</descrizione>
           </errore>
        </ricevutaNonOk>
     </RicevutaLavoratore>
  </Body>
 </Envelope>

Realizzare un web service con Mirth[modifica]

Finora ho realizzato applicazioni Mirth che leggevano da servizi web. E' interessante anche sapere che i web service si possono fare con Mirth. Il contesto è questo: un'azienda realizza un prodotto (ad esempio: un laboratorio che produce l'analisi di un campione di sangue) e il dato deve essere trasmesso all'azienda sanitaria perché lo registri nel suo gestionale clinico. L'azienda sanitaria realizza un servizio web che verrà chiamato dal laboratorio il quale spedirà al servizio il referto con un messaggio HL7. All'arrivo del messaggio l'azienda sanitaria esegue il parsing del messaggio e salva nel gestionale (un database relazionale) i dati.

Nella fattispecie il messaggio viene "affettato" a righe e viene salvata una intestazione e una serie di dettagli collegati, uno per ogni riga del messaggio.

L'impianto è questo:

Il source[modifica]

Il source è un SOAP listener che risponde con un WDSL che Mirth stesso genera e che mette a disposizione un metodo standard detto acceptMessage() (teniamo d'occhio ma per il momento soprassediamo sulla casella di selezione Respond from)

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Le destination[modifica]

Le destination sono parecchie perché la lavorazione del messaggio è piuttosto laboriosa: devo capire il tipo di messaggio (che leggo nell'intestazione del messaggio stesso) e a seconda di questo compiere diverse operazioni: per messaggi di un tipo estraggo dal file HL7 un file PDF che salvo nel NAS, e poi, in ogni caso, devo salvare in una tabella Oracle una intestazione e in una tabella figlia tutte le righe del messaggio numerandole e collegandole alla testata con un vincolo di chiave esterna:

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Un passetto in più: lo script[modifica]

Per questo tipo di applicazione devo personalizzare lo script che viene eseguito una volta eseguita l'applicazione del canale: con questo personalizzo la risposta del web service al programma che lo ha chiamato. Nelle figure precedenti si possono vedere questi punti in ciascuna delle 4 tab superiori.

Anche se ci sono diversi prodotti già attivi all'interno di Mirth per eseguire ognuna di queste operazioni atomiche, per convenienza o per forza alcune cose me le sono dovute scrivere a mano in JavaScript utilizzando classi embedded di Mirth, come la classe DatabaseConnectionFactory. Per esempio mi serviva eseguire una lettura di Oracle in una delle destinazioni, ma nelle distination non si può selezionare il tipo di connettore DatabaseReader che invece si può richiamare dal source. Quindi me lo sono fatto a mano. Ciò significa che, pur essendo possibile selezionare dei tipi di connettori standard che sono anche semplici da usare (ad esempio: FileWriter: gli passo la directory, il nome del file e il contenuto e lui me lo scrive dentro il filesystem), alcuni tipi di connettori dovevano comportarsi in modo non standard, ma Mirth è programmabile! per cui ho potuto estendere le funzionalità scrivendo i programmi a mano. Per me che non sono tanto in confidenza con il Java, scrivere in JavaScript in modo così approfondito (che è un po' meno rigido del Java) è stata comunque un'esperienza formativa.

Alla fine di questo lavoro, salvare i dati, bisognava rispondere al software che ha chiamato il servizio e: come si fa? Non lo so.

Ho usato per la prima volta la quarta TAB (Scripts). Ho selezionato "Postprocessor" nella select Script in alto (vedi figura), ho definito una serie di variabili e una istruzione di scrittura nel log, e poi se la variabile di canale error è valorizzata (e, se succede qualcosa, la valorizzo nelle destinazioni precedenti - esse vengono eseguite nell'ordine una alla volta), istanzio un tipo di risposta altrimenti un'altra.

Il cuore di tutto è l'oggetto di Mirth responseMap che mi permette di modificare quel messaggio di risposta del metodo di default acceptMessageResponse che avevamo lasciato in sospeso nel primo punto. Il valore che questa variabile può assumere non è una stringa ma un oggetto che viene inizializzato dal metodo ResponseFactory.getSuccessResponse(ack) in caso di OK, oppure dal metodo ResponseFactory.getFailureResponse(ko) in caso di KO (ack e ko invece sono due stringhe che definisco io all'inizio dello script). La presenza dell'istruzione responseMap.put() in questo script mi fa comparire la voce acceptMessageResponse nella tendina di selezione Respond from del source! Il tutto è riportato in figura:

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Come ultimo passaggio ecco come si presenta la chiamata al WS fatta da soapUI (a sinistra) e la response del servizio (a destra):

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Di soapUI ne parlo più avanti. Buona questa risposta nel forum di Mirth

LDAP[modifica]

Mi serve interrogare LDAP da Mirth. Questo il responso ad un quesito analogo messo nel forum di Mirthconnect:

[1]

NON ESISTE! vediamo che librerie LDAP Javascript esistano :s

Risorse web[modifica]

FAQ[modifica]

Configuration file not found[modifica]

  java.sql.SQLException: Configuration file not found

Questo errore succede quando definiamo un gestore pool con un nome:

  var pools = [
  {
     name:"jdbc/pool/appname",
     url:"jdbc:oracle:thin:username/password@dbhost.mydomain.com:1521:instname"
  }

e ne invochiamo un altro nell'istruzione SQL :

  java.sql.DriverManager.getConnection('jdbc:apache:commons:dbcp:jdbc/pool/appname1/', userDb, paswDb);

Pulizia e riavvio[modifica]

Mi è capitato questa settimana (3/4/12) di avere Mirth di test a cui non riuscivo ad accedere con la password di prima.

Il problema non era che era cambiata la password ma che la partizione /opt era piena.

Occorreva fare pulizia dei logs e riavviare

1) per fare la pulizia dei log: accedere a nettomcattest02 con l'utente mirth

 $ rm /opt/Mirth/logs/[quello che serve]

2) per riavviare

  $ kill -9 [pid-di-Mirth]
  $ /opt/Mirth/mirth[Invio]

Documentazione sulle API java e javascript per Mirth[modifica]

 svn/tags/1.8.1/server/src/com/webreach/mirth/server/util/DatabaseConnectionFactory.java


Cifratura di uno dei campi dell'XML[modifica]

Questa applicazione (INPS) richiede la cifratura di uno dei campi da passare. Ho usato due alternative:

  • invoco l'utility del sistema operativo che compie la cifratura (apache)
  • utilizzo una funzione java del pacchetto
 it.unige.disi.util.DM240604 

la seconda è più affidabile in quanto per la prima ho problemi di sincronizzazione (lancio un task parallelo nel sistema operativo che non so quando risponderà).

Il codice che utilizzo è questo (editare il transformer del Source):

var     pincode = msg['pin_code'].toString();
var certificate = '/home/mirth/cert/SanitelCF.cer';
try 
{
   var encoder = new Packages.it.unige.disi.util.DM240604();
   encoder.loadCertificateFile(certificate);
   var pincode_enc = encoder.crypt(pincode);
   channelMap.put('pincode_enc', pincode_enc);
}
catch (error)
{
   channelMap.put('pincode_enc', );
   logger.error('Mirth non ha prodotto la cifratura del pincode => ' + error);
}

Occorre però, prima, installare nella configurazione di Mirth il pacakge disi_certutils.jar nella directory /opt/Mirth/lib

Start / Stop di mirth[modifica]

Nella macchina netmirthtest:

  • stop
$ ps ax | grep mirth
1614 ?        Ss     0:00 sshd: mirth [priv]
1616 ?        S      0:00 sshd: mirth@pts/3
6338 pts/3    S      0:00 /bin/sh ./mirth.sh
6339 pts/3    Sl     0:15 java -Xmx256m -classpath mirth-launcher.jar:lib/log4j-1.2.13.jar:conf/ com.webreach.mirth.server.launcher.MirthLauncher mirth-launcher.xml
7122 pts/3    S+     0:00 grep mirth
$ kill 6338
  • start
$ cd /opt/Mirth
$ nohup ./mirth.sh & <invio> <invio>

Scope delle variabili[modifica]

Le variabili definite come globali (quelle che popolano il dizionario globalMap) non possono essere di tipo boolean (non funzionano).

Così funziona:

 definire Variable = debug e Mapping = 1;
 var debug = (globalMap.get('debug') == 1);

debug sarà TRUE;

Così non funziona

 definire Variable = debug e Mapping = true;
 var debug = (globalMap.get('debug'));

debug sarà undefined.

Connector, Channel, Global Channel, Global[modifica]

  • Connector: variabile locale al connettore (es. allo script)
  • Channel: variabile accessibile al canale per il tempo di vita di un messaggio (da source all'ultima destination): le variabili lette da una query database vivono qui
  • Global Channel: variabile accessibile al canale per il tempo di vita del canale: ad esempio la stringa di connessione al database vive qui.
  • Global: variabile accessibile da tutti i canali.

Manipolazione degli HL7[modifica]

Ho dovuto eseguire la cosa seguente:

  • sbustare il messaggio HL7 da SOAP;
  • salvare la testata in Oracle
  • se il documento HL7 è di tipo MDM, estrarre l'allegato contenuto nel campo OBX
  • salvare il documento nel NAS sotto la directory yyyy/mm/dd/nomefile.pdf.p7m
  • per ogni riga
    • salvarla in un'altra tabella Oracle
    • se la riga è di tipo TXA, al 16° segnaposto | (msg['TXA']['TXA.16']) scrivere il path completo del NAS in cui è stato salvato il file.
    • invocare una procedura Oracle che controlla il dato e restituire al chiamante la sua stringa di risposta.

Uno dei punti più delicati è il penultimo. Ho percorso tre strade per poter arrivare alla soluzione.

1) modifica della riga di testo TXA utilizzando le espressioni regolari: FAIL. Da questo punto di vista attenzione ad applicare la funzione text.replace(regexp, newString) se text è una stringa Java ma non Javascript!!! da' errore di applicazione del costruttore (The choice of Java constructor replace matching JavaScript argument types (function,string) is ambiguous;), occorre prima trasformare la stringa text java in una stringa javascript con la seguente istruzione:

 text = text + “”;

dopodiché l'applicazione della regexp

 /[\|]{n}/ 

si comporta in modo stocastico (non mi becca la n-esima occorrenza di | e fa sostituzioni non richieste).

2) modifica della riga di testo TXA utilizzando la funzione split: FAIL: questa istruzione non riconosce il needle | (e nemmeno ^; riconosce solo &); modifica del messaggio XML attraverso l'istruzione

 msg['TXA']['TXA.16'] = $('oggi') + '/' + $('filename') + ".pdf.p7m";

poi riconverto l'XML in HL7

 var raw = SerializerFactory.getHL7Serializer(false, false, true).fromXML(msg);

e procedo con lo split delle righe.

Attenzione: l'uso del Filter mi permette di modificare il messaggio raw PRIMA dell'esecuzione dello step di destination. Se uso il transformer, non funziona (Mirth esegue il transformer dopo aver eseguito lo step di destination).

Problemi all'avvio dell'applet Mirth Connect Administrator[modifica]

  • Sintomi: parte lo splash di Java 7 o Mirth Connect Administrator, ma subito dopo compare un errore contenente le parole "Missing attribute security manifest".
  • Diagnosi: l'applet è considerata non attendibile e non sicura dall JRE
  • Soluzione: da consolle digitare
 $ javaws -viewer

Si apre un pannello di controllo, cliccare sulla scheda Security e aggiungere l'url del server mirth all'elenco dei siti attendibili.

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Premere Ok e far ripartire il Mirth WebStart (ad esempio cliccando su "Launch Mirth Connect Administrator" sulla pagina web): stavolta dovrebbe comparire il prompt di login.

In Windows systems, the way to access the Java Conrol Panel - Java 7 Update 40 (7u40) and subsequents: A partire da Java 7 Update 40, potete individuare il Pannello di controllo Java mediante il menu Start di Windows.

  • Aprite il menu Start di Windows
  • Fate clic su Programmi
  • Individuate la lista di programmi Java
  • Fate clic su Configura Java per avviare il Pannello di controllo Java

here more details

Scripts[modifica]

Ciascun canale supporta quattro script analoghi agli script globali. Il motivo per il quale usare questi script all'interno del canale è per separare le preoccupazioni. In questo modo, una logica particolare può esssere associata al canale specifico. La versione di default di ciascuno di questi script non fa nulla. I quattro script sono

  • Deploy
  • Shutdown
  • Preprocessor
  • Postprocessor

Deploy[modifica]

Lo script viene eseguito ogni volta che Mirth viene avviato. Solo la globalMap è disponibile per memorizzare i dati in modo persistente. Lo script di deploy può essere usato per costruire e inizializzare oggetti comuni che hanno bisogno di persistere mentre Mirth è in esecuzione. I dati nella Global Map sono condivisi tra tutti i canali.

Shutdown[modifica]

Questo script viene eseguito ogni volta che Mirth viene fermato. Solo la globalMap è disponibile per memorizzare i dati in modo persistente. Lo script di shutdown viene tipicamente usato per pulire gli oggetti creati dallo script di deploy.

Preprocessor[modifica]

Questo script viene eseguito ogni volta che viene ricevuto un messaggio e PRIMA che questo venga normalizzato in XML. Sono disponibili anche le variabili di canale oltre a quelle globali.

Postprocessor[modifica]

Lo script viene eseguito subito DOPO che il messaggio sia stato inviato. Sono disponibili anche le variabili di canale oltre a quelle globali.

Connector Types[modifica]

Carrellata dei tipi di connettore

Applicazione con SOAP Listener e Database Writer[modifica]

Parto da ciò che ho trovato in un forum di Mirth ([2]):

 Ho appena iniziato con Mirth e sto cercando di impostare un piccolo progetto che esegue una richiesta ADT-A19 di un messaggio SOAP. 
 Ho alcuni problemi con questa configurazione però.
 1) A quanto pare può essere assegnato qualsiasi destinazione URI che voglio ma è sempre basata in una cartella chiamata "servizi" 
 e ha un nome fisso singolo metodo chiamato "AcceptMessage".
 2) Dopo una giornata davvero frustrante ho scoperto che perché il canale accetti l'ovvio formato dati XML devo urlencodare 
 i dati del messaggio SOAP. Io non saprei nemmeno da dove cominciare con gli altri formati che posso scegliere, ma sono sicuro 
 che se l'avessi fatto non avrei mai messo quelli in SOAP.
 3) Non sembra esserci alcun modo per formattare la risposta SOAP, così ora ho un "acceptMessageReturn" che contiene una serie
 di codici HL7 che l'applicazione non capisce.
 Così ora sto pensando ho bisogno di un qualche tipo di busta http (s) della pagina che farà la ridenominazione necessaria e traduzioni 
 dal livello di applicazione a qualcosa che Mirth può utilizzare e indietro. Ma non riesco nemmeno a trovare la DocumentRoot
 Sarebbe questo mi ha veramente bisogno di avere un webserver secondo principio attivo di tradurre e rotta verso Mirth? Inoltre, 
 come posso impostare gli indirizzi per Mirth in ascolto su localhost?

Ecco e adesso?[modifica]

Creo un nuovo canale Mirth; questo è il Source, un listener SOAP:

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Attenzione: l'indirizzo esterno è quello che deve essere invocato dal cliente, per cui va scritto un indirizzo pubblico. Si deve togliere lo spunta che forza l'External Address ad essere uguale all'Internal Address (Use Listener Address) e Mirth popola questo campo con l'indirizzo composto con i campi che ora risultano scrivibili; in particolare abbiamo:

  • l'External address:
 netmirthtest.mydomain.eu
  • la port
 8081
  • il nome del servizio
 Mirth

Se si invoca questo indirizzo da browser,

 http://netmirthtest.mydomain.eu:8081/services/Mirth?wsdl

il servizio ritorna il file wdsl con la descrizione del servizio:

 <?xml version="1.0"?>
 <definitions targetNamespace="http://components.mule.server.mirth.webreach.com">
   <message name="acceptMessageResponse">
   <part name="acceptMessageReturn" type="xsd:string">
   </part>
   </message>
   <message name="acceptMessageRequest">
   <part name="in0" type="xsd:string">
   </part>
   </message>
   <portType name="_Proxy7">
   <operation name="acceptMessage" parameterOrder="in0">
     <input message="impl:acceptMessageRequest" name="acceptMessageRequest">
   </input>
     <output message="impl:acceptMessageResponse" name="acceptMessageResponse">
   </output>
   </operation>
   </portType>
   <binding name="MirthSoapBinding" type="impl:_Proxy7">
   <binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
   <operation name="acceptMessage">
     <operation soapAction=""/>
     <input name="acceptMessageRequest">
       <body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://DefaultNamespace" use="encoded"/>
     </input>
     <output name="acceptMessageResponse">
       <body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://components.mule.server.mirth.webreach.com" use="encoded"/>
     </output>
   </operation>
   </binding>
   <service name="_Proxy7Service">
   <port binding="impl:MirthSoapBinding" name="Mirth">
     <address location="http://netmirthtest.mydomain.eu:8081/services/Mirth"/>
   </port>
   </service>
 </definitions>
  1. [soapui soapUI]

Il connettore Web service listener[modifica]

Cliccando sulla linguetta Source possiamo selezionare il Source type

  • WebService Listener
 * Listener Address / port
 * Service name (default Mirth)
 * WSDL Url
 * Method (String AcceptMessage(String message))
 * Respond from: 1 canale oppure dal postprocessor (dalla variabile di canale acceptMessageResponse:
   return responseMap.put('acceptMessageResponse', ResponseFactory.getSuccessResponse(ack));
 * Web service: Default o custom: se default la response è costruita utilizzando la classe standard di mirthconnect  [ResponseFactory: http://javadocs.mirthcorp.com/connect/3.0.1/user-api/com/mirth/connect/server/userutil/ResponseFactory.html]: Provides methods to create Response objects.

Metodi (esempio)[modifica]

  static Response getErrorResponse(java.lang.String message) 

Returns a Response representing a erred message.

  static Response  getFailureResponse(java.lang.String message) 

Deprecated. This method is deprecated and will soon be removed. Please use getErrorResponse(message) instead.

  static Response  getFilteredResponse(java.lang.String message) 

Returns a Response representing a filtered message. ...

Se custom possiamo scrivere la nostra classe per gestire le response.

Email sender[modifica]

Dalla versione di MC 2.2 è stato rinominato in SMTP Sender

Rotto tutto: come uscirne?[modifica]

Mirth out-of-the-box, come detto, usa come database Apache Derby. Per configurare DB diversi, occorre agire sul file

  /opt/mirthconnect/conf/mirth.properties

In ogni caso, ad un certo punto impatto con questo errore che mi nega l'accesso all'interfaccia Java:

  java.sql.SQLException: Failed to start database '/opt/Mirth/mirthdb'

Questo problema si verifica sempre quando il database è pieno, ovvero ha riempito la queta disco assegnata all'utente mirth. Nel mio caso ho una tabella (che poi si rileva essere la tabella APP.MESSAGES) che ha raggiunto i 3GB di dimensione. Per accedere al database uso il client ij di Derby, contenuto nel pacchetto derbytools.jar (di solito il file ha anche un numero di versione, tipo derbytools-10.5.3.0.jar. Questi file si trovano nella sottodirectory lib/ della home di Mirth). Una volta impostata correttamente la classpath come descritto in seguito, si fa così:

  $ java org.apache.derby.tools.ij
  ij> connect 'jdbc:derby:/opt/mirthconnect/mirthdb';
  ij> delete from message;

qui ci può mettere molto tempo, proporzionalmente (circa) alla dimensione del file mirthdb/seg0/ .dat contenetnte i messaggi.

Io sfortunamamente sono incappato in un caso particolarmente complicato, in cui il file contenete la tabella MESSAGES è a 3GB e non ho più spazio nemmeno per la creazione di un bit nella directory /tmp/. Questo causa l'errore che segue

ERROR 25502: An SQL data change is not permitted for a read-only connection, user or database.

che è fuorviante perché non è un problema di attribuzione di permessi (i file del database sono tutti dello user mirth per cui non c'è motivo che il database non consenta di alterarli; inoltre il processo mirth stesso è attribuito all'utente mirth), quanto della mancanza di spazio disco!!!.

Quindi da superuser devo aumentare la quota disco all'utente mirth che finalmente può lanciare lo statement di cancellazione righe senza far comparire il messaggio di errore:

  ij> delete from message;

solo che devo aspettare un po'. Alla fine

  3854 rows inserted/updated/deleted
  ij> commit;

una verifica allo spazio su disco mi dice che è tutto ok:

  $ du --si
  1,1M  ./log
  6,7M  ./seg0
  4,1k  ./tmp
  7,8M  .

Occorre però fare girare un ulteriore script:

  ij> call SYSCS_UTIL.SYSCS_COMPRESS_TABLE('APP', 'MESSAGE', 0);
  0 rows inserted/updated/deleted
  ij>

e riavviare Mirth:

  $ mcservice stop
  Shutting down mcservice
  Stopped.
  $ mcservice start
  Starting mcservice
  $

Dopo questa operazione sono in grado di accedere nuovamente alla consolle di amministrazione.

Suggerimento[modifica]

MI è capitato di dover controllare il contenuto di file trasmessi con messaggi SOAP per capire un problema. Se si fa una cosa del genere, disabilitare quanto prima l'ouptut di interi file su log perché così la tabella message si riempie molto rapidamente.

DerbyDb[modifica]

Non riesco a connettermi al Derby remoto, ho bisgno di un client a linea di comando. Preventivamente installo Derby nel mio pc Fonte

Download[modifica]

  $ wget http://apache.fis.uniroma2.it//db/derby/db-derby-10.10.1.1/db-derby-10.10.1.1-bin.tar.gz

Installazione[modifica]

  # mkdir /opt/Apache 
  # cp db-derby-10.10.1.1-bin.tar.gz /opt/Apache 
  # cd /opt/Apache 
  # tar xzvf db-derby-10.10.1.1-bin.tar.gz

Imposto le variabili di ambiente[modifica]

  $ export DERBY_INSTALL=/opt/Apache/db-derby-10.10.1.1-bin

Questa la aggiungo io

  $ export DERBY_HOME=/opt/Apache/db-derby-10.10.1.1-bin

Configuro Embedded Derby

  $ export CLASSPATH=$DERBY_INSTALL/lib/derby.jar:$DERBY_INSTALL/lib/derbytools.jar:.
  $ cd $DERBY_INSTALL/bin 
  $ . setEmbeddedCP 

Verifica[modifica]

  $ java org.apache.derby.tools.sysinfo
  ------------------ Informazioni su Java ------------------
  Versione Java:    1.8.0-ea
  Fornitore Java:     Oracle Corporation
  Home Java:       /usr/lib/jvm/java-8-oracle/jre
  Classpath Java:  /opt/Apache/db-derby-10.10.1.1-bin/lib/derby.jar:/opt/Apache/db-derby-10.10.1.1-bin/lib/derbytools.jar:
                   /opt/Apache/db-derby-10.10.1.1-bin/lib/derby.jar:/opt/Apache/db-derby-10.10.1.1-bin/lib/derbytools.jar:.
  Nome SO:         Linux
  Architettura SO: amd64
  Versione SO:     3.5.0-34-generic
  Nome utente Java: marcob
  Home utente Java: /home/marcob
  Dir utente Java: /opt/Apache/db-derby-10.10.1.1-bin/bin
  java.specification.name: Java Platform API Specification
  java.specification.version: 1.8
  java.runtime.version: 1.8.0-ea-b94
  --------- Informazioni su Derby --------
  [/opt/Apache/db-derby-10.10.1.1-bin/lib/derby.jar] 10.10.1.1 - (1458268)
  [/opt/Apache/db-derby-10.10.1.1-bin/lib/derbytools.jar] 10.10.1.1 - (1458268)
  ------------------------------------------------------
  ----------------- Informazioni sulle impostazioni nazionali -----------------
  Impostazioni nazionali correnti:  [italiano/Italia [it_IT]]
  È stato trovato il supporto per le impostazioni nazionali: [cs]
         versione: 10.10.1.1 - (1458268)
  È stato trovato il supporto per le impostazioni nazionali: [de_DE]
         versione: 10.10.1.1 - (1458268)
  È stato trovato il supporto per le impostazioni nazionali: [es]
         versione: 10.10.1.1 - (1458268)
  È stato trovato il supporto per le impostazioni nazionali: [fr]
         versione: 10.10.1.1 - (1458268)
  È stato trovato il supporto per le impostazioni nazionali: [hu]
         versione: 10.10.1.1 - (1458268)
  È stato trovato il supporto per le impostazioni nazionali: [it]
         versione: 10.10.1.1 - (1458268)
  È stato trovato il supporto per le impostazioni nazionali: [ja_JP]
         versione: 10.10.1.1 - (1458268)
  È stato trovato il supporto per le impostazioni nazionali: [ko_KR]
         versione: 10.10.1.1 - (1458268)
  È stato trovato il supporto per le impostazioni nazionali: [pl]
         versione: 10.10.1.1 - (1458268)
  È stato trovato il supporto per le impostazioni nazionali: [pt_BR]
         versione: 10.10.1.1 - (1458268)
  È stato trovato il supporto per le impostazioni nazionali: [ru]
         versione: 10.10.1.1 - (1458268)
  È stato trovato il supporto per le impostazioni nazionali: [zh_CN]
         versione: 10.10.1.1 - (1458268)
  È stato trovato il supporto per le impostazioni nazionali: [zh_TW]
         versione: 10.10.1.1 - (1458268)
  echo $CLASSPATH
  /opt/Apache/db-derby-10.10.1.1-bin/lib/derby.jar:/opt/Apache/db-derby-10.10.1.1-bin/lib/derbytools.jar:
  /opt/Apache/db-derby-10.10.1.1-bin/lib/derby.jar:/opt/Apache/db-derby-10.10.1.1-bin/lib/derbytools.jar:.

ij[modifica]

ij è il client nativo che viene su con Derby. È a linea di comando (wow). Proviamolo

  marcob@js:/opt$ sudo chown -R marcob:marcob Apache/
  cd Apache/db-derby-10.10.1.1-bin/
  $ java org.apache.derby.tools.ij
  Versione ij 10.10
  ij> 
  ij> connect 'jdbc:derby:MyDbTest;create=true';
  ij> (solo dopo un po')
  ij> exit;
  $ cat derby.log
  ----------------------------------------------------------------
  Tue Jul 02 10:56:13 CEST 2013:
  Avvio della versione di Derby The Apache Software Foundation - Apache Derby - 10.10.1.1 - (1458268): istanza a816c00e-013f-9e98-ab73-000002e37410
  sulla directory di database /opt/Apache/db-derby-10.10.1.1-bin/MyDbTest con caricatore classi sun.misc.Launcher$AppClassLoader@2c7b84de 
  Caricato da file:/opt/Apache/db-derby-10.10.1.1-bin/lib/derby.jar
  java.vendor=Oracle Corporation
  java.runtime.version=1.8.0-ea-b94
  user.dir=/opt/Apache/db-derby-10.10.1.1-bin
  os.name=Linux
  os.arch=amd64
  os.version=3.5.0-34-generic
  derby.system.home=null
  Programma di caricamento classe database avviato - derby.database.classpath=
  ----------------------------------------------------------------
  Tue Jul 02 10:57:21 CEST 2013: arresto in corso del motore di Derby
  ----------------------------------------------------------------
  Tue Jul 02 10:57:21 CEST 2013:
  Arresto dell'istanza a816c00e-013f-9e98-ab73-000002e37410 nella directory del database /opt/Apache/db-derby-10.10.1.1-bin/MyDbTest 
  con il caricatore di classi sun.misc.Launcher$AppClassLoader@2c7b84de 
  ----------------------------------------------------------------

Abbiamo creato un database. Ora colleghiamoci:

  ij> connect 'jdbc:derby:MyDbTest';
  ij> create table derbyDB(num int, addr varchar(40)); 
  0 righe inserite/aggiornate/eliminate
  ij> insert into derbyDB values (1956,'Webster St.');
  1 riga inserita/aggiornata/eliminata
  ij> insert into derbyDB values (1910,'Union St.');
  1 riga inserita/aggiornata/eliminata
  ij> update derbyDB set num=180, addr='Grand Ave.' where num=1956; 
  1 riga inserita/aggiornata/eliminata
  ij> select * from derbyDb;
  NUM        |ADDR                                    
  ----------------------------------------------------
  180        |Grand Ave.                              
  1910       |Union St.                               
  
  2 righe selezionate

Squirrel[modifica]

Ad un certo punto il database è diventato enorme e non riesco più a fare login.

Di solito la soluzione è alleggerire il database. Ma Mirth out-of-the-box è configurato per lavorare con un database opensource creato da Apache, che è Derby.

Per leggere database derby c'è un tool, sempre Apache, che si chiama Squirrel. Lo installo.

 $ wget http://sourceforge.net/projects/squirrel-sql/files/1-stable/3.5.0/squirrel-sql-3.5.0-install.jar/download
 $ java -jar squirrel-sql-3.5.0-install.jar

Seguono alcune schermate di installazione, riporto le salienti.

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione
Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione
Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione
Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Primo lancio di Squirrel[modifica]

When you first launch SQuirreL it will create a directory called .squirrel-sql in your C:\Documents and Settings\<username> directory on Windows, or $HOME on Linux.

Select the Apache Derby Embedded option from the Drivers window and click the pencil icon (or double-click), which allows you to Modify the Selected Driver. We need to point to the location of the derby.jar file on the file system, which contains the Derby Embedded Driver. Click the Extra Class Path tab, and then the Add button.

  marcob@js:~$ cd Development/squirrel-sql-3.5.0/
  marcob@js:~/Development/squirrel-sql-3.5.0$ find . -name "derby.jar"
  ./plugins/derby.jar

No, non è qui, faccio a modo mio e configuro il Derby Client anziché l'embedded. Poi mi scarico il client da qui

  $ wget http://repo.maven.apache.org/maven2/org/apache/derby/derbyclient/10.9.1.0/derbyclient-10.9.1.0.jar

e lo copio tra i plugin

  marcob@js:~/Development/squirrel-sql-3.5.0/plugins$ cp /home/marcob/Documenti/Marco/software/database/squirrel/derbyclient-10.9.1.0.jar .

Ora lo carico da GUI

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

La notifica in basso

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

E la selezione del driver

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Ora occorre attaccarsi ad un database vero e proprio; il client propone questo URI predisposto

  jdbc:derby://<server>[:<port>]/<databaseName>[;<URL attribute>=<value>]

che personalizzo così

  jdbc:derby://test04.mirth.mydomain.eu:7071/mirthdb

Salvo e il driver è così personalizzato

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Ora creo un alias

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Speranza vana se Derby non crea un socket TCP, comunque.

Problemi[modifica]

Avvio di Mirthconnect Administration Console[modifica]

Clicco sul pulsante MirthConnect Administrator, mi chiede un'applicazione per far partire il file jnlp, seleziono javaws da una delle directory:

  • /usr/lib/jvm/java-6-oracle/bin/javaws
  • /usr/lib/jvm/java-7-oracle/bin/javaws
  • /usr/lib/jvm/java-8-oracle/bin/javaws

(di solito la più recente), MA dopo aver scaricato e verificato il file JNPL java mi avverte:

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Tentando di ignorare l'alert ho un definitivo errore bloccante:

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Di solito rimediavo a questo errore con la procedura indicata come descritto qui, però non sempre funziona

Versioni[modifica]

3.3[modifica]

  • Code Template Libraries — Code templates can now be organized into libraries, enabled for specific channels and JavaScript contexts, and can even be included with channel imports / exports! Tons of other enhancements too, like revision history support with the Channel History extension!
  • JSON Data Type — Automatically converts between JavaScript objects and JSON strings for you, and uses a JSON-specific structure in the transformer message tree.
  • Enhanced Polling Connector Settings — Create consistent channel schedules with on-the-hour polling settings, the ability to use specific days of the week or month, and active time ranges. You can even use cron expressions for maximum flexibility!
  • Advanced SFTP Settings — Use RSA public-key authentication, enable / disable host key signature validation, and set other advanced configuration options.


Inclusione di classi[modifica]

Le funzionalità di Mirth si possono estendere scivendo delle classi personalizzate che poi vanno agganciate a Mirth nel modo che segue

Scrittura della classe JarTest1[modifica]

   package com.example;
   public class JarTest {
        public JarTest() {
             // ATTENZIONE: costruttore: la sua presenza non cambia il problema
        }
        public String returnSomething() {
            return "Hello, World!";
        }
   }

Il file si trova all'interno di questa struttura di cartelle:

   ├── src
   │   ├── com
   │   │   └── example
   │   │       └── JarTest.java

Compilazione della classe (come da istruzioni [3])[modifica]

   $ cd ~/Documenti/clienti/aop/2017/webservices/sci/plurima/getDDT
   $ javac -d classes src/com/example/*
   $ ll classes/com/example/
   totale 12
   drwxrwxr-x 2 marcob marcob 4096 mar 13 14:24 ./
   drwxrwxr-x 3 marcob marcob 4096 mar 13 12:41 ../
   -rw-rw-r-- 1 marcob marcob  305 mar 23 15:15 JarTest.class

Il file compilato quindi si troverà sotto la directory classes

   ├── classes
   │   └── com
   │       └── example
   │           └── JarTest.class

Creazione del package (stessa directory sopra)[modifica]

   $ jar -cf JarTest.jar -C classes com
   $ ll
   totale 236
   drwxrwxr-x 4 marcob marcob   4096 mar 23 15:19 ./
   drwxrwxr-x 3 marcob marcob   4096 mar  7 15:45 ../
   drwxrwxr-x 3 marcob marcob   4096 mar 13 12:41 classes/
   -rw-rw-r-- 1 marcob marcob    905 mar 23 15:19 JarTest.jar
   drwxrwxr-x 4 marcob marcob   4096 mar  7 15:27 src/

l'opzione -C classes fa in modo che jar cambi la sua directory di lavoro sotto la directory class e com fa in modo che la directory più esterna del package sia com(/example/JarTest.class)

Contenuto del pacchetto:[modifica]

   $ jar tf JarTest.jar
   META-INF/
   META-INF/MANIFEST.MF
   com/
   com/example/
   com/example/JarTest.class

Deposito del package nel server sotto /opt/mithconnect/custom-lib[modifica]

   $ scp JarTest.jar mirth@test04.mirth:/opt/mirthconnect/custom-lib

Verifico che il pacchetto sia lì:[modifica]

   -bash-3.2$ ll
   totale 20
   -rw-r--r-- 1 mirth appusers 9342 28 gen  2014 disi_certutils.jar
   -rw-r--r-- 1 mirth appusers  905 23 mar 15:28 JarTest.jar

Riavvio di mirth[modifica]

   -bash-3.2$ mcservice stop
   Shutting down mcservice
   Stopped.
   -bash-3.2$ ps ax | grep mirth
    1911 pts/0    S+     0:00 grep mirth
   30144 ?        Ss     0:00 sshd: mirth [priv]
   30164 ?        S      0:00 sshd: mirth@pts/0
   -bash-3.2$ mcservice start
   Starting mcservice
   -bash-3.2$ 

Utilizzo della classe all'interno di una destination:[modifica]

   var obj = new Packages.com.example.JarTest();
   logger.info('[sci_plurima_getddt]: ' +obj.returnSomething());

Start del canale[modifica]

   Errore:
   [2017-03-23 15:32:23,130]  ERROR (org.mule.impl.DefaultComponentExceptionStrategy:95): Caught exception in Exception Strategy for: c2009c97-de42-4a6c-8e62-745d03e65399: java.lang.Exception: org.mozilla.javascript.EcmaError: TypeError: [JavaPackage com.example.JarTest] is not a function, it is object. (1fcd6b84-94f3-4aac-b392-1d5b00a99abd#16)
   java.lang.Exception: org.mozilla.javascript.EcmaError: TypeError: [JavaPackage com.example.JarTest] is not a function, it is object. (1fcd6b84-94f3-4aac-b392-1d5b00a99abd#16)
       at com.mirth.connect.connectors.js.JavaScriptMessageDispatcher.doDispatch(JavaScriptMessageDispatcher.java:96)
       at com.mirth.connect.connectors.js.JavaScriptMessageDispatcher.doSend(JavaScriptMessageDispatcher.java:103)
   

Nota bene: se io elimino il pacchetto dalla directory (ad esempio lo rinomino in JarTest.1.jar) il messaggio di errore non cambia! In effetti il forum riporta questa interpretazione:

   Stuck on ... is not a function, it is object. 
   So based on Roy's comment it seems that it cannot load the  .jar package

Provo a modificare la gerarchia di cartelle[modifica]

il sorgente, anziché porlo in una gerarchia

   ├── src
   │   ├── com
   │   │   └── example
   │   │       └── JarTest.java

lo pongo così

   ├── com
   │   └── example
   │       └── JarTest.java


Rifatto la compilazione, il package, il deploy, il restart: non cambia nulla