Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Correct the URL for 2.0.0 shrine-dashboard.

...

Shrine now accesses the DSA's database directly from inside shrine-api.war. It no longer needs a special QEP user to authenticate to the Data Steward service. Delete that user from the PM cell, and remove this section from shrine.conf:

...

Remove includeAggregateResults

Remove the formerly required "includeAggregateResults =  false" from shrine.conf . 

Code Block
languagebash
themerdark
includeAggregateResults = false


Configure the webclient in shrine.conf

In SHRINE 2.0.0, you will need additional parameters to configure the behavior of the webclient. Please add this section in shrine.conf:

Code Block
languagebash
themerdark
webclient {
   domain = "i2b2demo"
   name  = "SHRINE"
   siteAdminEmail = "email@example.com"
   usernameLabel = "User Name"
   passwordLabel = "User Password"
   defaultNumberOfOntologyChildren = 10000  // the number of children to show when an ontology folder is expanded.
   queryFlaggingInstructions = "Enter instructions for flagging queries here"
   flaggingPlaceholderText = "Enter placeholder text for the query flagging text input field"
   flaggingIconInstructions = "Enter text for when user mouses over the flagging information icon in the header of the Query History here"
 }


The webclient has hard-coded default values for the userNameLabel, passwordLabel, and defaultNumberOfOntologyChildren fields if they are not configured; userNameLabel defaults to "SHRINE User", passwordLabel defaults to "SHRINE Password", and defaultNumberOfOntologyChildren defaults to 10000.

...


Info

Before you perform these steps, please make sure your Tomcat version is at least 8.5.x, but please do not install Tomcat version 9!


The URL to the SHRINE Webclient has changed from https://shrine_The URL to the SHRINE Webclient has changed from https://shrine_url:6443/shrine-webclient to https://shrine_url:6443/shrine-api/shrine-webclient.

...

1. Add rewrite valve to conf/server.xml inside the Host configuration section

<Host name="localhost" appBase="webapps"
            unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />

2. Create a file name rewritename rewrite.config in config in conf/Catalina/localhost with the following contents

RewriteRule ^/shrine-webclient/* /shrine-api/shrine-webclient
RewriteRule ^/steward/* /shrine-api/shrine-steward
RewriteRule ^/shrine-dashboard/* /shrine-api/shrine-dashboard

No need to specify a slick driver anymore

...

Here's a sample shrine.conf for a 2.0.0 downstream node (it might be helpful to copy the entire contents of this file and then replace with your own institution's specific values):

Code Block
languagebash
themeRDark
titleshrine.conf
shrineHubBaseUrl = "https://shrine_hub_url:6443"  //The shrine hub's URL as observed from this tomcat server
i2b2BaseUrl = "http://localhost:9090"             //The local i2b2's URL as observed from this tomcat server
i2b2Domain = "i2b2demo"                           //recommended to change this to a unique domain
i2b2ShrineProjectName = "SHRINE"

shrine {

  nodeKey = "unique-node-name" 	//node key to get information from the hub about this node
  shrineDatabaseType = "mysql" 	//can be oracle, mysql, sqlserver

  messagequeue {
    blockingq {
      serverUrl = ${shrineHubBaseUrl}/shrine-api/mom  //point this to the network hub
    }
  }

  webclient {
   domain = ${i2b2Domain}
   name  = ${i2b2ShrineProjectName}
   siteAdminEmail = "shrine-admin@exampleemail@example.com"
  }

 usernameLabel pmEndpoint {= "User Name"
   passwordLabel url = ${i2b2BaseUrl}/i2b2/services/PMService/getServices
  }"User Password"
  ontEndpoint {
defaultNumberOfOntologyChildren = 10000  url = ${i2b2BaseUrl}/i2b2/services/OntologyService/
  }

  hiveCredentials {
    domain = ${i2b2Domain}/ the number of children to show when an ontology folder is expanded.
   queryFlaggingInstructions username= = "demo"
Enter instructions for flagging passwordqueries = here"demouser"
    crcProjectIdflaggingPlaceholderText = "Demo"
    ontProjectId = ${i2b2ShrineProjectName}
  }

  breakdownResultOutputTypes {
    PATIENT_AGE_COUNT_XML {
      description = "Age patient breakdown"
    }
    PATIENT_RACE_COUNT_XMLEnter placeholder text for the query flagging text input field"
   flaggingIconInstructions = "Enter text for when user mouses over the flagging information icon in the header of the Query History here"
  }

  pmEndpoint {
    url  description = "Race patient breakdown"${i2b2BaseUrl}/i2b2/services/PMService/getServices
  }
  ontEndpoint  }{
    PATIENT_VITALSTATUS_COUNT_XML {url = ${i2b2BaseUrl}/i2b2/services/OntologyService/
  }

  hiveCredentials {
 description = "Vital Statusdomain patient breakdown"
= ${i2b2Domain}
    username = }"demo"
    PATIENT_GENDER_COUNT_XML {password = "demouser"
      descriptioncrcProjectId = "Demo"Gender
 patient breakdown"
  ontProjectId = ${i2b2ShrineProjectName}
  } //end breakdown section

  hubbreakdownResultOutputTypes {
    clientPATIENT_AGE_COUNT_XML {
      serverUrldescription = ${shrineHubBaseUrl} "Age patient breakdown"
    }
  }

  queryEntryPointPATIENT_RACE_COUNT_XML {
    broadcasterServiceEndpoint {
 description = "Race   url = ${shrineHubBaseUrl}/shrine/rest/broadcaster/broadcastpatient breakdown"
    }
  }

  adapterPATIENT_VITALSTATUS_COUNT_XML {
    crcEndpoint {
 description = "Vital Status patient urlbreakdown"
 = ${i2b2BaseUrl}/i2b2/services/QueryToolService/
    }

     adapterMappingsFileName = "AdapterMappings.csv"
PATIENT_GENDER_COUNT_XML {
      //crcRunQueryTimeLimitdescription = "30Gender patient secondsbreakdown"
 // in seconds, use quotes. default 30 seconds }
  } //end adapterbreakdown section

  keystorehub {
    client {
 file  = "/opt/shrine/shrine.keystore"
  serverUrl  password = "password"${shrineHubBaseUrl}
    privateKeyAlias}
 = "your_private_key_alias" }

  queryEntryPoint {
  keyStoreType  =broadcasterServiceEndpoint "JKS"{
    caCertAliases  url = ["shrine-hub-ca"]${shrineHubBaseUrl}/shrine/rest/broadcaster/broadcast
    }
 //end keystore section }

  stewardadapter {
    createTopicsModecrcEndpoint ={
 Approved //the default is Pending -url the most secure - but most sites use Approved= ${i2b2BaseUrl}/i2b2/services/QueryToolService/
    }

    emailDataSteward {adapterMappingsFileName = "AdapterMappings.csv"
    crcRunQueryTimeLimit  sendAuditEmails = false"30 seconds" //false toin turnseconds, offuse thequotes. wholedefault works30 ofseconds
 emailing the} data//end stewardadapter section

  keystore  {
    file = "//interval = "1 day" //Audit researchers dailyopt/shrine/shrine.keystore"
    password = "password"
    privateKeyAlias  //timeAfterMidnight = "6 hours" //Audit researchers at 6 am. If the interval is less than 1 day then this delay is ignored.
      //maxQueryCountBetweenAudits = 30 //If a researcher runs more than this many queries since the last audit audit heryour_private_key_alias"
    keyStoreType = "JKS"
    caCertAliases = ["shrine-hub-ca"]
  } //end keystore section

  steward {
    createTopicsMode = Approved //the default is Pending - the most secure - but most sites use Approved

    emailDataSteward {
      //minTimeBetweenAuditssendAuditEmails = "30false days" //Iffalse ato researcherturn runsoff atthe leastwhole oneworks query,of auditemailing thosethe queriesdata ifsteward this much time has passed
   
   //interval = "1 day" //YouAudit mustresearchers providedaily
 the email address of the shrine node system admin, to handle bounces and invalid addresses
      //from = "shrine-admin@example.com" //timeAfterMidnight = "6 hours" //Audit researchers at 6 am. If the interval is less than 1 day then this delay is ignored.
      //YoumaxQueryCountBetweenAudits must= provide30 the//If emaila addressresearcher ofruns themore datathan steward
this many queries since the last //toaudit = "shrine-steward@example.com"
   audit her
      //subjectminTimeBetweenAudits = "Audit30 SHRINE researchersdays"
 //If a researcher runs at //Theleast baseUrlone forquery, theaudit datathose stewardqueries toif bethis substitutedmuch intime tohas emailpassed
 text. Must be
 supplied if it is used in   //You must provide the email text.
      //stewardBaseUrl = "https://example.com:6443/shrine-api/steward/" address of the shrine node system admin, to handle bounces and invalid addresses
      externalStewardBaseUrl//from = "https://example.com:6443/shrine-api/steward/shrine-admin@example.com"
   
   //You must provide //Textthe toemail useaddress forof the emaildata audit.steward
      //AUDIT_LINES will be replaced by a researcherLine for each researcher to audit.to = "shrine-steward@example.com"
   
      //subject = "Audit SHRINE researchers"
      //STEWARD_BASE_URL will be replaced by the valueThe baseUrl for the data steward to be substituted in stewardBaseUrlto ifemail availabletext.
 Must be supplied if it //emailBodyis = """Please audit used in the following users at STEWARD_BASE_URL at your earliest convenience: AUDIT_LINES"""email text.
      //notestewardBaseUrl that this can be a multiline message= "https://example.com:6443/shrine-api/shrine-steward/"
      externalStewardBaseUrl = "https://example.com:6443/shrine-api/shrine-steward/"
   
      //Text to use perfor researcherthe toemail audit.
      //FULLNAME, USERNAME, COUNT and LAST_AUDIT_DATELINES will be replaced withby appropriatea text.
researcherLine for each researcher to audit.
 //researcherLine = "FULLNAME (USERNAME) has run COUNT queries since LAST_AUDIT_DATE."
    }

    database { //STEWARD_BASE_URL will be replaced by the value in stewardBaseUrl if available.
      dataSourceFrom//emailBody = ""JNDI"
Please audit the following users  jndiDataSourceName = "java:comp/env/jdbc/stewardDBat STEWARD_BASE_URL at your earliest convenience: AUDIT_LINES"""
      slickProfileClassName//note = "slick.jdbc.MySQLProfile$"
     that this can be a multiline message
   
      //Text to use per researcher to audit.
          //slick.jdbc.H2Profile$
          FULLNAME, USERNAME, COUNT and LAST_AUDIT_DATE will be replaced with appropriate text.
      //researcherLine = "FULLNAME (USERNAME) has run COUNT queries       //slick.jdbc.PostgresProfile$since LAST_AUDIT_DATE."
    }
  } //end steward section
                     //slick.jdbc.SQLServerProfile$
                              //slick.jdbc.JdbcProfile$
                              //slick.jdbc.OracleProfile$
    } //end steward database section
  } //end steward section
  
} //end shrine

Changes to SHRINE databases

In SHRINE 2.0.0, there are a couple of database changes that you will need to perform to accommodate the new tables and structures needed for SHRINE to work properly. 

...


} //end shrine
Warning
titleNew nodeKey parameter

The nodeKey parameter will be used to identify your node from the Hub, so we advise that it should be a relatively unique identifier along with the network in which you are in, ie. HarvardProdNode or similar. If you have any questions, please contact the network administrator for more information.


Changes to SHRINE databases

In SHRINE 2.0.0, there are a couple of database changes that you will need to perform to accommodate the new tables and structures needed for SHRINE to work properly. 

Remove the PRIVILEGED_USER table and associated constraints and sequences from your database


Code Block
languagesql
themerdark
use shrine_query_history;
DROP TABLE PRIVILEGED_USER;


Drop the column of actual patient counts from the adapter's COUNT_RESULT table

Shrine no longer needs to store the actual (and mildly sensitive) actual count of patients from the CRC in its COUNT_RESULT table. In mysql remove it from the shrine_query_history database with


Code Block
languagesql
themerdark
use shrine_query_history;
ALTER TABLE COUNT_RESULT DROP TABLECOLUMN PRIVILEGEDORIGINAL_USERCOUNT;


Drop the column of actual patient counts from the adapter'

...

s BREAKDOWN_

...

RESULT table

Shrine no longer needs to store the actual (and mildly sensitive) actual count of patients from the CRC in its COUNTBREAKDOWN_RESULT tableRESULT table. In mysql remove it from the shrine_query_history database with


Code Block
languagesql
themerdark
use shrine_query_history

...

;
ALTER TABLE BREAKDOWN_RESULT DROP COLUMN ORIGINAL_VALUE;


Add a status column for queries at the QEP

Add a status column to qepAuditDB's previousQueries table to support updates in query status with :

MySQL:


Code Block
languagesql
themerdark
use 
shrine_query_history
qepAuditDB;
ALTER TABLE 
COUNT_RESULT
previousQueries 
DROP
ADD COLUMN 
ORIGINAL_COUNT;

Drop the column of actual patient counts from the adapter's BREAKDOWN_RESULT table

...

status VARCHAR(255) NOT NULL DEFAULT 'Before V26';


MS SQL:


Code Block
languagesql
themerdark
use 
shrine_query_history
qepAuditDB;
ALTER TABLE 
BREAKDOWN_RESULT DROP COLUMN ORIGINAL_VALUE;

Add a status column for queries at the QEP

Add a status column to qepAuditDB's previousQueries table to support updates in query status with :

...

previousQueries ADD status VARCHAR(MAX) NOT NULL DEFAULT 'Before V26';


ORACLE:


Code Block
languagesql
themerdark
use qepAuditDB;
ALTER TABLE "previousQueries" ADD COLUMN "status" VARCHARVARCHAR2(255256) NOT NULL DEFAULT 'Before V26' NOT NULL;
MS SQL


Added table QUERY_PROBLEM_DIGESTS

MySQL:


Code Block
languagesql
theme
rdark
RDark
use qepAuditDB;
ALTER TABLE previousQueries ADD COLUMN 'status' VARCHAR(MAX)
create table QUERY_PROBLEM_DIGESTS (NETWORKQUERYID BIGINT NOT NULL, CODEC TEXT NOT NULL, STAMP TEXT NOT NULL, SUMMARY TEXT NOT NULL, DESCRIPTION TEXT NOT NULL, 
DEFAULT
DETAILS 
'Before V26';

ORACLE:

Code Block
languagesql
themerdark
use qepAuditDB;
ALTER TABLE "previousQueries" ADD COLUMN "status" VARCHAR2(256) DEFAULT 'Before V26' NOT NULL;

Added table QUERY_PROBLEM_DIGESTS

TEXT NOT NULL, CHANGEDATE BIGINT NOT NULL);
create index queryProblemsNetworkIdIndex on QUERY_PROBLEM_DIGESTS(NETWORKQUERYID);


MS SQLMySQL:


Code Block
languagesqlSQL
themeRDarkrdark
use qepAuditDB;
create table "QUERY_PROBLEM_DIGESTS" ("NETWORKQUERYID" BIGINT NOT NULL, "CODEC" TEXTVARCHAR(MAX) NOT NULL, "STAMP" TEXTVARCHAR(MAX) NOT NULL, "SUMMARY" TEXTVARCHAR(MAX) NOT NULL, "DESCRIPTION" TEXTVARCHAR(MAX) NOT NULL, "DETAILS" TEXTVARCHAR(MAX) NOT NULL, "CHANGEDATE" BIGINT NOT NULL);
create index "queryProblemsNetworkIdIndex" on "QUERY_PROBLEM_DIGESTSDIGESTS" ("NETWORKQUERYID");



MS SQLORACLE:


Code Block
languageSQL
themerdark
use qepAuditDB;
create table "QUERY_PROBLEM_DIGESTS" ("NETWORKQUERYID" BIGINTNUMBER(19) NOT NULL,"CODEC" VARCHAR(MAX256) NOT NULL,"STAMP" VARCHAR(MAX256) NOT NULL,"SUMMARY" VARCHAR(MAX)CLOB NOT NULL,"DESCRIPTION" VARCHAR(MAX)CLOB NOT NULL,"DETAILS" VARCHAR(MAX)CLOB NOT NULL,"CHANGEDATE" BIGINTNUMBER(19) NOT NULL);
create index "queryProblemsNetworkIdIndex" on "QUERY_PROBLEM_DIGESTS" ("NETWORKQUERYID");


Added table RESULTS_OBSERVED

MySQLORACLE:


Code Block
languageSQL
themerdark
use qepAuditDB;
create table "QUERY_PROBLEM_DIGESTS" ("NETWORKQUERYID" NUMBER(19) NOT NULL,"CODEC" VARCHAR(256) NOT NULL,"STAMP" VARCHAR(256)
create table RESULTS_OBSERVED (NETWORKQUERYID BIGINT NOT NULL,"SUMMARY" CLOB CHECKSUM BIGINT NOT NULL,"DESCRIPTION" CLOB OBSERVEDTIME BIGINT NOT NULL,"DETAILS" CLOB NOT NULL,"CHANGEDATE" NUMBER(19) NOT NULL));
create index resultsObservedQueryIdIndex on RESULTS_OBSERVED(NETWORKQUERYID);
create index "queryProblemsNetworkIdIndex"resultsObservedChecksumIndex on "QUERY_PROBLEM_DIGESTS" ("NETWORKQUERYID"RESULTS_OBSERVED(CHECKSUM);

Added table RESULTS_OBSERVED


MySQLMS SQL:


Code Block
languageSQL
themerdark
use qepAuditDB;
create table "RESULTS_OBSERVED" ("NETWORKQUERYID" BIGINT NOT NULL, "CHECKSUM" BIGINT NOT NULLNOTNULL, "OBSERVEDTIME" BIGINT NOT NULL);
create index "resultsObservedQueryIdIndex" on "RESULTS_OBSERVED" ("NETWORKQUERYID");
create index "resultsObservedChecksumIndex" on "RESULTS_OBSERVED" ("CHECKSUM");


MS SQLORACLE:


Code Block
languageSQL
themerdark
use qepAuditDB;
create table `RESULTS"RESULTS_OBSERVED`OBSERVED" (`NETWORKQUERYID` BIGINT"NETWORKQUERYID" NUMBER(19) NOT NULL,`CHECKSUM` BIGINT"CHECKSUM" NUMBER(19) NOT NULL,`OBSERVEDTIME` BIGINT"OBSERVEDTIME" NUMBER(19) NOT NULL);
create index "resultsObservedQueryIdIndex" on "RESULTS_OBSERVED" ("NETWORKQUERYID");
create index "resultsObservedChecksumIndex" on "RESULTS_OBSERVED" ("CHECKSUM");

...

" on "RESULTS_OBSERVED" ("CHECKSUM");


Make sure you have setenv.sh defined for Tomcat startup

For SHRINE 2.0.0 in addition to the 2.0.1 ACT ontology, we will need to make sure that Tomcat has enough resources to load the ontology and its larger Adapter Mappings file. To do this, you will need to define a setenv.sh file within the tomcat/bin directory:

Code Block
languageSQLbash
themerdark
use qepAuditDB;
create table "RESULTS_OBSERVED" ("NETWORKQUERYID" NUMBER(19) NOT NULL,"CHECKSUM" NUMBER(19) NOT NULL,"OBSERVEDTIME" NUMBER(19) NOT NULL);
create index "resultsObservedQueryIdIndex" on "RESULTS_OBSERVED" ("NETWORKQUERYID");
create index "resultsObservedChecksumIndex" on "RESULTS_OBSERVED" ("CHECKSUM");#!/bin/bash# Set Tomcat options to prevent hanging thread on shutdown
export CATALINA_OPTS=" -XX:MaxPermSize=256m -Dakka.daemonic=on "
 
# Set Tomcat options to prevent resource problems with larger ontology v2.0.1
CATALINA_OPTS="$CATALINA_OPTS -server -Xms1024m -Xmx2048m -Duser.timezone=America/New_York



Start SHRINE

Warning
titlePLEASE NOTE

At this time, please reach out to the network hub administrator so that they can add your individual node to the network with the "nodeKey" that was identified in shrine.conf. Once added to the hub, your node should then start sending and receiving queries. You'll also need to tell the admin your domain parameter, so that the domain will be associated with the nodeKey on the hub.


The only thing left to do at this point is start SHRINE back up. Simply do the following:

...

Code Block
languagebash
themerdark
https://your_shrine_host:6443/shrine-api/shrine-dashboard

This is a sample screenshot of the upgraded 2.0.0 dashboard:

...