IHE support
Concepts
The IPF provides support for several IHE profiles. The basic idea is to offer a Camel component for each IHE transaction. These components ensure that the technical requirements of the profile are met by applications built on top of the IPF IHE support.
Quick reference
All IPF IHE components are named according to the profile and transaction that they implement. Each component is provided using its own Maven artifact. All Maven artifacts have the same group ID (org.openehealth.ipf.platform-camel). The following table shows a summary of the available components:
| IHE Transaction ID | Description | IPF IHE component | Maven artifact ID |
|---|---|---|---|
| ITI-8 | Patient Identity Feed (PIX Feed) | pix-iti8 xds-iti8 |
platform-camel-ihe-pix-iti8 |
| ITI-9 | PIX Query | pix-iti9 | platform-camel-ihe-pix-iti9 |
| ITI-10 | PIX Update Notification | pix-iti10 | platform-camel-ihe-pix-iti10 |
| ITI-21 | Patient Demographics Query (PDQ) | pdq-iti21 | platform-camel-ihe-pdq-iti21 |
| ITI-22 | Patient Demographics and Visit Query (PDQ) | pdq-iti22 | platform-camel-ihe-pdq-iti22 |
| ITI-14 | XDS.a Register Document Set | xds-iti14 | platform-camel-ihe-xds-iti14 |
| ITI-15 | XDS.a Provide & Register Document Set | xds-iti15 | platform-camel-ihe-xds-iti15 |
| ITI-16 | XDS.a Query Registry | xds-iti16 | platform-camel-ihe-xds-iti16 |
| ITI-17 | XDS.a Retrieve Document | xds-iti17 | platform-camel-ihe-xds-iti17 |
| ITI-18 | XDS.a+b Registry Stored Query | xds-iti18 | platform-camel-ihe-xds-iti18 |
| ITI-41 | XDS.b Provide & Register Document Set | xds-iti41 | platform-camel-ihe-xds-iti41 |
| ITI-42 | XDS.b Register Document Set | xds-iti42 | platform-camel-ihe-xds-iti42 |
| ITI-43 | XDS.b Retrieve Document Set | xds-iti43 | platform-camel-ihe-xds-iti43 |
The package structure of the IHE support is the following:
XDS.b
The IHE XDS.b profile mandates the use of the web service technology. The IPF provides these web services in conformance with the specification, together with their WSDL documents. The XDS.b actors (Registry, Repository, Source and Consumer) are not directly implemented by the IPF. Instead, the transactions required by the actors are offered via components that create endpoints for both the client and server sides. An application assembles these components to build the actors:

Note that registries are also required to support the PIX feed transaction, which is covered in the corresponding section.
XDS standard conformance
The IPF implementation of the XDS profiles conforms to Version 5.0 (December 2008) of the IHE infrastructure technical framework with the addition of the final texts of the change proposals up to CP 426.
Because the XDS components do not represent a full implementation of the XDS actors, they cannot fulfill all parts of the specification. E.g. they cannot check whether a patient ID is known to the registry. Such checks need to be performed within the route implementation. The following list should give a brief overview of the parts of the requirements that have been met by the IPF implementation:
- protocol specific requirements: most notably those listed in Appendix V of the ITI Technical Framework Volume 2 (Web Services for IHE Transactions). This includes WS-Addressing, SOAP 1.2/1.1 and mustUnderstand attributes in SOAP headers.
- meta class model requirements: as listed in chapter 4 of the ITI Technical Framework Volume 2 (Cross-Transaction Specifications). This also includes transformations between ebXML classes and meta model classes where applicable.
- stored query classes: as an extension to the meta model, simplified classes have been defined for each stored query type specified in section 3.18 of the ITI Technical Framework Volume 2 (Registry Stored Query).
XDS.b configuration
To use of the IPF XDS.b components in an application, you have to add the dependencies of the transaction components to your pom.xml, e.g. for the ITI-18 component:
<dependency> <groupId>org.openehealth.ipf.platform-camel</groupId> <artifactId>platform-camel-ihe-xds-iti18</artifactId> <version>${ipf-version}</version> </dependency>
The web service implementation within the IPF component is based on Apache CXF. The necessary dependencies are transitively included via the above dependency. CXF itself can be used in various ways. For the purpose of this documentation we will use Spring configuration via imports and deploy the components into Apache Tomcat. The following snippet is an example for an application context that imports all relevant CXF and IPF beans:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel="http://activemq.apache.org/camel/schema/spring" xmlns:cxf="http://activemq.apache.org/camel/schema/cxfEndpoint" xsi:schemaLocation="http://activemq.apache.org/camel/schema/cxfEndpoint http://activemq.apache.org/camel/schema/cxfEndpoint/camel-cxf.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://activemq.apache.org/camel/schema/spring http://activemq.apache.org/camel/schema/spring/camel-spring.xsd "> <!-- Importing the CXF configuration --> <import resource="classpath:META-INF/cxf/cxf.xml"/> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/> <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/> <import resource="classpath:META-INF/cxf/cxf-extension-addr.xml"/> <camel:camelContext id="camelContext"> <camel:jmxAgent id="agent" disabled="true"/> </camel:camelContext> <bean id="producerTemplate" factory-bean="camelContext" factory-method="createProducerTemplate"/> <bean id="routeBuilder" depends-on="routeModelExtender" class="org.openehealth.ipf.platform.camel.ihe.xds.iti18.GroovyRouteBuilder"> </bean> <bean id="coreModelExtension" class="org.openehealth.ipf.platform.camel.core.extend.CoreModelExtension"> </bean> <bean id="xdsModelExtension" class="org.openehealth.ipf.platform.camel.ihe.xds.core.extend.XDSModelExtension"> </bean> <bean id="routeModelExtender" class="org.openehealth.ipf.platform.camel.core.extend.DefaultModelExtender"> <property name="routeModelExtensions"> <list> <ref bean="coreModelExtension" /> <ref bean="xdsModelExtension" /> </list> </property> </bean> </beans>
Deployment within Tomcat is done by defining a web.xml that references the above application context as well as instantiating a CXF-related servlet. A simple setup could look like this:
<?xml version="1.0"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <display-name>Test IPF IHE Web-App</display-name> <context-param> <!-- configures the classpath of the Spring application context --> <param-name>contextConfigLocation</param-name> <param-value>classpath:path/to/your/context.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <servlet-name>CXFServlet</servlet-name> <servlet-class> org.apache.cxf.transport.servlet.CXFServlet </servlet-class> </servlet> <servlet-mapping> <!-- configures the address of the servlet path under which our web services are published --> <servlet-name>CXFServlet</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> </web-app>
Exposing an XDS.b service
Similar to other Camel components, the XDS.b components are used within your routes:
from('xds-iti18:myIti18Service')
...
This statement creates a web service that implements the ITI-18 transaction and publishes it under the service name myIti18Service. The full path of the service URL is made up by the web container and the servlet configuration. With the above configuration, the service will be published under http://HOSTNAME:PORT/WEBAPP/services/myIti18Service, where HOSTNAME is the name of the machine that the service is running on, PORT represents the TPC/IP port configured within the web container (e.g. in Tomcat you can configure this in server.xml, default value is 8080), and WEBAPP is a name that depends on your web application deployment (in Tomcat this is simply the name of the directory of the web application). More information about how to setup a simple web application with Apache Tomcat can be found here.
Secure transport can be used with the XDS.b services by configuring your container. There is no additional configuration required for IPF XDS components. Details on how to configure Apache Tomcat with SSL support can be found here.
Making calls to an XDS.b service
You access an XDS.b service within a route similar to other Camel endpoints:
...
.to('xds-iti18://localhost:8080/myWebApp/services/myIti18Service')
The whole endpoint URI resembles the service URL as it was described in the previous section. The only difference is that the protocol name is changed from http to xds-iti18.
Per default, all requests will be sent using SOAP 1.2, as prescribed by the specification. To switch to SOAP 1.1, URL parameter soap11=true can be used. Note that because of a bug in CXF, XDS.b consumer components will produce SOAP 1.2 responses independently from the actual SOAP version used in requests. This will be corrected as soon as the new CXF version will be available for the IPF.
Secure transport via HTTPS can be configured by adding the URL parameter secure=true. The following sample shows a call to a registry via SOAP 1.1 over HTTPS:
...
.to('xds-iti18://localhost:8080/myWebApp/services/myIti18Service?secure=true&soap11=true')
In addition, the HTTP client used by CXF must be configured as well. This is done within the application context according to the CXF documentation:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:camel="http://activemq.apache.org/camel/schema/spring" xmlns:cxf="http://activemq.apache.org/camel/schema/cxfEndpoint" xmlns:util="http://www.springframework.org/schema/util" xmlns:http="http://cxf.apache.org/transports/http/configuration" xmlns:sec="http://cxf.apache.org/configuration/security" xsi:schemaLocation=" http://activemq.apache.org/camel/schema/cxfEndpoint http://activemq.apache.org/camel/schema/cxfEndpoint/camel-cxf.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd http://activemq.apache.org/camel/schema/spring http://activemq.apache.org/camel/schema/spring/camel-spring.xsd http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd "> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <http:conduit name="*.http-conduit"> <http:tlsClientParameters disableCNCheck="true"> <sec:keyManagers keyPassword="changeit"> <sec:keyStore type="JKS" password="changeit" file="keystore" /> </sec:keyManagers> <sec:trustManagers> <sec:keyStore type="JKS" password="changeit" file="keystore" /> </sec:trustManagers> <sec:cipherSuitesFilter> <!-- these filters ensure that a ciphersuite with export-suitable or null encryption is used, but exclude anonymous Diffie-Hellman key change as this is vulnerable to man-in-the-middle attacks --> <sec:include>.*_EXPORT_.*</sec:include> <sec:include>.*_EXPORT1024_.*</sec:include> <sec:include>.*_WITH_DES_.*</sec:include> <sec:include>.*_WITH_NULL_.*</sec:include> <sec:exclude>.*_DH_anon_.*</sec:exclude> </sec:cipherSuitesFilter> </http:tlsClientParameters> </http:conduit> ...
Message types
Messages sent between XDS.b actors use a payload defined by ebXML 3.0. The profile specifies how messages are created to represent requests and responses as well as document entries, submission sets and folders. Besides the support of raw ebXML 3.0 messages, the IPF offers a model to abstract from the underlying details of transforming and validating ebXML 3.0 messages.
Raw ebXML 3.0 support
The body of input and output messages depends on the transaction:
| Transaction | Input message body | Output message body |
|---|---|---|
| ITI-18 | org.openehealth.ipf.commons.ihe.xds.core.stub.ebrs30.query.AdhocQueryRequest | org.openehealth.ipf.commons.ihe.xds.core.stub.ebrs30.query.AdhocQueryResponse |
| ITI-41 | org.openehealth.ipf.commons.ihe.xds.core.ebxml.ebxml30.ProvideAndRegisterDocumentSetRequestType | org.openehealth.ipf.commons.ihe.xds.core.stub.ebrs30.rs.RegistryResponseType |
| ITI-42 | org.openehealth.ipf.commons.ihe.xds.core.stub.ebrs30.lcm.SubmitObjectsRequest | org.openehealth.ipf.commons.ihe.xds.core.stub.ebrs30.rs.RegistryResponseType |
| ITI-43 | org.openehealth.ipf.commons.ihe.xds.core.ebxml.ebxml30.RetrieveDocumentSetRequestType | org.openehealth.ipf.commons.ihe.xds.core.ebxml.ebxml30.RetrieveDocumentSetResponseType |
The IPF also provides the necessary ebRS 3.0 classes that are referenced within these types. All ebRS 3.0 related classes can be found in the sub-packages of org.openehealth.ipf.commons.ihe.xds.core.stub.ebrs30.
Simplified model classes
ebXML 3.0 message bodies can be converted to a simplified model. The following table shows the types that can be used for each transaction:
| Transaction | Input message body | Output message body |
|---|---|---|
| ITI-18 | org.openehealth.ipf.commons.ihe.xds.core.requests.QueryRegistry | org.openehealth.ipf.commons.ihe.xds.core.responses.QueryResponse |
| ITI-41 | org.openehealth.ipf.commons.ihe.xds.core.requests.ProvideAndRegisterDocumentSet | org.openehealth.ipf.commons.ihe.xds.core.responses.Response |
| ITI-42 | org.openehealth.ipf.commons.ihe.xds.core.requests.RegisterDocumentSet | org.openehealth.ipf.commons.ihe.xds.core.responses.Response |
| ITI-43 | org.openehealth.ipf.commons.ihe.xds.core.requests.RetrieveDocumentSet | org.openehealth.ipf.commons.ihe.xds.core.responses.RetrievedDocumentSet |
These model classes can be used via type converters, as shown in the following Groovy route:
import static org.openehealth.ipf.commons.ihe.xds.core.responses.Status.* import org.apache.camel.spring.SpringRouteBuilder import org.openehealth.ipf.commons.ihe.xds.core.requests.QueryRegistry import org.openehealth.ipf.commons.ihe.xds.core.requests.query.FindDocumentsQuery import org.openehealth.ipf.commons.ihe.xds.core.responses.QueryResponse import org.openehealth.ipf.commons.ihe.xds.core.metadata.ObjectReference import org.openehealth.ipf.platform.camel.core.util.Exchanges public class RouteBuilder extends SpringRouteBuilder { @Override public void configure() throws Exception { from('xds-iti18:myIti18Service') .convertBodyTo(QueryRegistry.class) .choice() // Return an object reference for a find documents query .when { it.in.body.query instanceof FindDocumentsQuery } .transform { def response = new QueryResponse(SUCCESS) response.references.add(new ObjectReference('document01')) response } // Any other query else is a failure .otherwise() .transform { new QueryResponse(FAILURE) } } }
This route only accepts the stored query FindDocuments. If it receives such a query, it returns a single reference to a document (document01). Any other query returns a failure response. Of course this route does not fulfill the functional requirements of the ITI-18 transaction (e.g. all stored query types must be supported by a registry). However, it shows how a registry can be implemented without directly using the ebXML 3.0 classes.
| convertBodyTo Note that convertBodyTo(QueryRegistry.class) is not strictly required. If it is not used, the conversion must be done when accessing the body. In this case the when statement needs to use it.in.getBody(QueryRegistry.class).query. This will leave the body unchanged. However, keep in mind that converting the ebXML object every time you need to access the body can be time consuming. |
Large document content
The transactions ITI-41 and ITI-43 have to send document content as part of their request or response messages. In practice such messages can become quite large. To allow for memory-efficient streaming of the document content, the aforementioned components rely on CXF's support for binary data. CXF streams the content on disk and then provides a DataHandler to access the file. Therefore, it is not necessary to use IPF's large binary support (LBS).
Validation
The XDS.b components provide functionality for transaction-specific validation of ebXML 3.0 messages. This validation uses the validate DSL extension of the IPF. The following code snippet shows an example of a validation in
from('xds-iti18:myIti18Service')
.validate().iti18Request()
... // Process the message and create a response.
.validate().iti18Response()
The corresponding DSL extensions for validation need to be included into the model extender. Make sure that the following beans are defined within your application context:
... <bean id="coreModelExtension" class="org.openehealth.ipf.platform.camel.core.extend.CoreModelExtension" /> <bean id="xdsModelExtension" class="org.openehealth.ipf.platform.camel.ihe.xds.core.extend.XDSModelExtension" /> <bean id="routeModelExtender" class="org.openehealth.ipf.platform.camel.core.extend.DefaultModelExtender"> <property name="routeModelExtensions"> <list> <ref bean="coreModelExtension" /> <ref bean="xdsModelExtension" /> <!-- ... other model extension bean if necessary ... --> </list> </property> </bean> ...
XDS.a
Support for XDS.a is similar to that of XDS.b. Most transactions presume web service-based endpoints; only ITI-17 directly uses HTTP for the download of documents. With the exception of ITI-18, which is the same in both XDS.a and XDS.b, XDS.a transaction numbers differ from those in XDS.b and use SOAP 1.1 and SwA (SOAP with Attachments) instead of SOAP 1.2 and MTOM respectively. The following image gives a quick overview of the actors and transactions involved in the XDS.a profile:

Note that the Registry actor has to support the PIX feed transaction, which is covered in the corresponding section.
Configuring, exposing and accessing of the XDS.a components are to be performed in the same way as in the case of XDS.b. As already mentioned above, the only significant difference is that the ITI-17 transaction is not implemented as a SOAP-based web service. Therefore, it requires a few additional steps that are mentioned in the next sections.
XDS standard conformance
The IPF implementation of the XDS profiles conforms to Version 5.0 (December 2008) of the IHE infrastructure technical framework with the addition of the final texts of the change proposals up to CP 426.
ITI-17 configuration
To offer the ITI-17 transaction for a repository implementation you have to add an additional servlet to your web.xml:
<?xml version="1.0"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <display-name>Test IPF IHE Web-App</display-name> <context-param> <!-- configures the classpath of the Spring application context --> <param-name>contextConfigLocation</param-name> <param-value>classpath:org/openehealth/ipf/platform/camel/ihe/xdsb/example/context.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <!-- Servlet used for all CXF web services --> <servlet-name>CXFServlet</servlet-name> <servlet-class> org.apache.cxf.transport.servlet.CXFServlet </servlet-class> </servlet> <servlet> <!-- Servlet used only for ITI-17 --> <servlet-name>Iti17Servlet</servlet-name> <servlet-class> org.openehealth.ipf.platform.camel.ihe.xds.iti17.servlet.Iti17Servlet </servlet-class> </servlet> <servlet-mapping> <!-- configures the address of the servlet path under which our web services are published --> <servlet-name>CXFServlet</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> <servlet-mapping> <!-- configures the address of the servlet path under which the ITI-17 transaction is published --> <servlet-name>Iti17Servlet</servlet-name> <url-pattern>/iti17/*</url-pattern> </servlet-mapping> </web-app>
Exposing the ITI-17 transaction
The ITI-17 transaction is exposed via
from('xds-iti17:myIti17Service')
...
The URL that this transaction is accessible under is determined by the ITI-17 servlet configuration in your web.xml. For the above sample web.xml, the URL results in http://HOSTNAME:PORT/WEBAPP/iti17/myIti17Service. Note that the servlet path (iti17) is different to that of other transactions (services) that use the CXFServlet.
Making calls to the ITI-17 transaction
Calling the ITI-17 transaction from a document consumer can be achieved via:
...
.to('xds-iti17://localhost:8080/myWebApp/iti17/myIti17Service')
Again, note the difference in the URL. The ITI-17 servlet is accessed through a different path than the CXFServlet.
Message types
Messages sent between XDS.a actors use ebXML 2.1 (ebXML 3.0 for ITI-18) as payload format. The profile specifies how messages are created to represent requests and responses as well as document entries, submission sets and folders. Besides the support for raw ebXML messages, the IPF offers a model to abstract from the underlying details of transforming and validating ebXML messages.
Raw ebXML 2.1/3.0 support
The body of input and output messages depend on the transaction:
| Transaction | Input message body | Output message body |
|---|---|---|
| ITI-14 | org.openehealth.ipf.commons.ihe.xds.core.stub.ebrs21.rs.SubmitObjectsRequest | org.openehealth.ipf.commons.ihe.xds.core.stub.ebrs21.rs.RegistryResponse |
| ITI-15 | org.openehealth.ipf.commons.ihe.xds.core.ebxml.ebxml21.ProvideAndRegisterDocumentSetRequestType | org.openehealth.ipf.commons.ihe.xds.core.stub.ebrs21.rs.RegistryResponse |
| ITI-16 | org.openehealth.ipf.commons.ihe.xds.core.stub.ebrs21.query.AdhocQueryRequest | org.openehealth.ipf.commons.ihe.xds.core.stub.ebrs21.rs.RegistryResponse |
| ITI-17 | String (document URL part) | InputStream |
| ITI-18 | org.openehealth.ipf.commons.ihe.xds.core.stub.ebrs30.query.AdhocQueryRequest | org.openehealth.ipf.commons.ihe.xds.core.stub.ebrs30.query.AdhocQueryResponse |
The IPF also provides the necessary ebRS 2.1 and 3.0 classes that are referenced within these types. All ebRS-related classes can be found in the sub-packages of org.openehealth.ipf.commons.ihe.xds.core.stub.ebrs30 and org.openehealth.ipf.commons.ihe.xds.core.stub.ebrs21.
The input of the ITI-17 transaction is the part of the document URL that is appended to the URL of the service. The exact structure depends on the implementation of the Repository actor. It can be a path, a query, or a combination of both:
| Document URL | ITI-17 input message body |
|---|---|
http://HOSTNAME:PORT/WEBAPP/iti17/myIti17Service/my/path/to/document |
/my/path/to/document |
http://HOSTNAME:PORT/WEBAPP/iti17/myIti17Service?docId=123 |
?docId=123 |
http://HOSTNAME:PORT/WEBAPP/iti17/myIti17Service/my/path?docId=321 |
/my/path?docId=321 |
Simplified model classes
ebXML message bodies can be converted to a simplified model. The following table shows the types that can be used for each transaction:
| Transaction | Message input body type | Message output body type |
|---|---|---|
| ITI-14 | org.openehealth.ipf.commons.ihe.xds.core.requests.RegisterDocumentSet | org.openehealth.ipf.commons.ihe.xds.core.responses.Response |
| ITI-15 | org.openehealth.ipf.commons.ihe.xds.core.requests.ProvideAndRegisterDocumentSet | org.openehealth.ipf.commons.ihe.xds.core.responses.Response |
| ITI-16 | org.openehealth.ipf.commons.ihe.xds.core.requests.QueryRegistry | org.openehealth.ipf.commons.ihe.xds.core.responses.QueryResponse |
| ITI-18 | org.openehealth.ipf.commons.ihe.xds.core.requests.QueryRegistry | org.openehealth.ipf.commons.ihe.xds.core.responses.QueryResponse |
For an example of how to use these classes, refer to the corresponding XDS.b section.
Large document content
XDS.a uses SOAP with Attachments (SwA) instead of MTOM, which is used in XDS.b. The implementation of SwA within CXF has to be checked for efficient support for large documents. This is currently an open issue. However, it only applies to the ITI-15 transaction that performs the "upload" of documents. The ITI-17 transaction is a simple HTTP GET download that results in an InputStream contained in the exchange. This allows efficient streaming of the document.
Validation
Apart from ITI-17, XDS.a messages are validated similar to XDS.b messages. For ITI-17 there is no validation support.
PIX + PDQ
The IPF provides components for PIX and PDQ transactions that use HL7 v.2 as data format and MLLP as transport protocol. The following picture shows the relevant actors and transactions:

In fact, these components represent extensions of the standard camel-mina component. Exactly as for XDS.a+b, the application's pom.xml must state the corresponding dependency, e.g. for PIX Feed (ITI-8):
<dependency> <groupId>org.openehealth.ipf.platform-camel</groupId> <artifactId>platform-camel-ihe-pix-iti8</artifactId> <version>${ipf-version}</version> </dependency>
This will automatically (transitively) involve, in particular, camel-mina, camel-hl7, HAPI and IPF HL7 processing support.
Making and accepting calls via PIX/PDQ endpoints
The URL format is the same for consumers and producers:
from('pix-iti8://0.0.0.0:8888?param1=value1¶m2=value2')
...
...
.to('pix-iti8://hostname.org:9090?param3=value3¶m4=value4')
Only parameters are optional, all other URL components are obligatory.
URL Parameters
There are two groups of URL parameters in the PIX/PDQ components: the ones inherited from the basis Camel components and the additional ones.
Differences between the PIX/PDQ components and camel-mina / camel-hl7
Some parameters defined in camel-mina have obtained constant values in the PIX/PDQ components. It means that these parameters are actually not configurable by the user any more; values provided via endpoint URLs are silently ignored. These parameters are the following:
| Parameter name | Type | Constant value in PIX/PDQ components |
|---|---|---|
| sync | boolean | true |
| lazySessionCreation | boolean | true |
| transferExchange | boolean | false |
| encoding | String | corresponds to the charset name configured for the HL7 codec factory, as described below |
Moreover, camel-hl7 defines a parameter named codec, which contains the name of a Spring bean that corresponds to an HL7 codec factory. PIX/PDQ components set "hl7codec" as a default value for this parameter. The user still has to define the corresponding bean, though:
<bean id="hl7codec" class="org.apache.camel.component.hl7.HL7MLLPCodec"> <property name="charset" value="iso-8859-1"/> </bean>
The character set name set up for the HL7 codec factory will be automatically
- propagated to the Camel component (see parameter encoding in the table above),
- stored in the Exchange.CHARSET_NAME property of each Camel exchange, and
- used in all data transformation activities.
Additional URL parameters
Besides the URL parameters pre-defined in camel-mina and camel-hl7, the PIX/PDQ components support additional parameters: secure, audit, and allowIncompleteAudit. They are are in fact common for all IPF IHE components and described here.
Handling of data types and exceptions
Incoming messages (i.e. requests on the consumer side and responses on the producer side) are automatically unmarshalled into IPF MessageAdapter's.
Outgoing messages on the producer side (i.e. requests) are expected to belong to one of the following types in order to be able to be successfully marshalled and sent:
- IPF MessageAdapter
- "raw" HAPI message
- String
- byte[]
- NIO ByteBuffer
- InputStream
- File
For outgoing messages on the consumer side (i.e. responses), the same set of data types as for the producer side requests is supported. An addition, the message body can contain an Exception instance, which will be transformed into a NAK response. Any exceptions thrown in the route will lead to NAK responses as well.
When neither the data type of the response message is supported nor an exception has been thrown in the route, the message header org.openehealth.ipf.platform.camel.ihe.mllp.core.MllpComponent.ACK_TYPE_CODE_HEADER will be taken into consideration. When the value of this header belongs to the enumeration type org.openehealth.ipf.modules.hl7.AckTypeCode, an acknowledgement will be automatically generated and sent back to the requestor — a positive one for AckTypeCode.AA, a negative one (NAK) for AckTypeCode.AE and AckTypeCode.AR.
When even this header is not set or when its value is not of desired type, the route fails.
Validation
Same as for XDS.a+b messages, the IPF provides a validation mechanism for PIX/PDQ requests and responses. To use it, corresponding DSL extensions should be activated in the application's Spring descriptor as shown below:
... <bean id="mllpModelExtension" class="org.openehealth.ipf.platform.camel.ihe.mllp.core.extend.MllpModelExtension"/> <bean id="routeModelExtender" class="org.openehealth.ipf.platform.camel.core.extend.DefaultModelExtender"> <property name="routeModelExtensions"> <list> <ref bean="coreModelExtension" /> <ref bean="mllpModelExtension" /> </list> </property> </bean> ...
After that, the validation can be performed using the validate DSL extension, e.g. for PIX Feed (ITI-8):
from('xds-iti8://0.0.0.0:9999?audit=false')
.onException(ValidationException.class)
.maximumRedeliveries(0)
.end()
.validate().iti8Request()
.process {
// generate a response
Exchanges.resultMessage(it).body = ...
}
.validate().iti8Response()
ATNA
ATNA auditing functionality is fully integrated into the corresponding IPF components. The only thing the user has to configure is the URI of the target syslog server, as described in the next section.
Configuring auditors
Each of the currently supported IHE actor types has a corresponding singleton auditor, i.e. the following set is available:
- XDSRegistryAuditor
- XDSRepositoryAuditor
- XDSSourceAuditor
- XDSConsumerAuditor
- PIXManagerAuditor (serves the Patient Demographic Supplier actor as well)
- PIXSourceAuditor
- PIXConsumerAuditor
- PDQConsumerAuditor
Auditors can be configured both individually and all together. Besides the syslog server URI mentioned above (actually the only mandatory parameter), the following optional parameters should be set up (see Section 5.4 of RFC 3881 for details):
- audit source ID
- audit enterprise site ID
| Warning Configuration of auditors is stored in instances of the class org.openhealthtools.ihe.atna.auditor.context.AuditorModuleConfig. These instances contain much more configurable fields than the three described here, but the user is actually not ought to change them. |
Individual configuration
To configure a particular auditor (for example, the XDS Registry-related one), the user can write
import org.openhealthtools.ihe.atna.auditor.context.AuditorModuleConfig; import org.openhealthtools.ihe.atna.auditor.XDSRegistryAuditor; ... AuditorModuleConfig config = new AuditorModuleConfig(); config.setAuditRepositoryHost("my.syslog.server"); config.setAuditRepositoryPort(514); config.setAuditSourceId("..."); config.setAuditEnterpriseSiteId("..."); XDSRegistryAuditor.getAuditor().setConfig(config);
To perform the same operation using Spring, the following obvious bean definitions can be used:
<bean id="config" class="org.openhealthtools.ihe.atna.auditor.context.AuditorModuleConfig"> <property name="auditRepositoryHost" value="my.syslog.server" /> <property name="auditRepositoryPort" value="514" /> <property name="auditSourceId" value="..." /> <property name="auditEnterpriseSiteId" value="..." /> </bean> <bean id="registryAuditor" class="org.openhealthtools.ihe.atna.auditor.XDSRegistryAuditor" factory-method="getAuditor"> <property name="config" ref="config" /> </bean>
Group configuration
From a Java application:
import org.openhealthtools.ihe.atna.auditor.context.AuditorModuleContext; ... AuditorModuleContext.getContext().getConfig().setAuditRepositoryHost("my.syslog.server"); AuditorModuleContext.getContext().getConfig().setAuditRepositoryPort(514);
Using Spring descriptor:
<bean id="iheAuditorContext" class="org.openhealthtools.ihe.atna.auditor.context.AuditorModuleContext" factory-method="getContext"> </bean> <bean id="iheAuditorConfig" factory-bean="iheAuditorContext" factory-method="getConfig"> <property name="auditRepositoryHost" value="my.syslog.server" /> <property name="auditRepositoryPort" value="514" /> </bean>
Disabling auditing
In order to disable auditing for a particular service endpoint (i.e. a Camel consumer) or for a particular client invocation (i.e. a Camel producer), the corresponding URL should be extended with parameter audit=false, e.g.
to('xds-iti18://localhost:9091/xds-iti18-service?audit=false')
or
from('xds-iti18:xds-iti18-service?audit=false')
Note that this feature is (currently) not supported for ITI-17.
Writing down incomplete audit records
Under some circumstances (for example, when the request does not contain all required elements) the system is not able to collect all necessary data to construct a well-formed audit record. Per default, no audit is performed in this case, because it would violate the specification.
But — as an exception, e.g. for debug purposes — the user can change this behavior by setting the parameter allowIncompleteAudit in the URL of the corresponding XDS to true:
to('xds-iti18://localhost:9091/xds-iti18-service?allowIncompleteAudit=true')
Of course, this setting will not have any effect when the auditing functionality is generally switched off, i.e. when the parameter audit in the mentioned endpoint URL was set to false, as described in the previous section.
Note that this feature is (currently) not supported for ITI-17.
Configure auditing transport: Reliable and special auditing
Default implementation of ATNA auditing is based on unreliable UDP communication (BSD Syslog protocol), as prescribed by the IHE IT TF, Vol. 2, Section 3.20.6.1. This choice is also explained in the ATNA FAQ.
In order to change this setting, a new implementation of org.openhealthtools.ihe.atna.auditor.sender.AuditMessageSender must be provided and registered via AuditorModuleContext.getContext().setSender(mySender).
The delivery queue can be customized in a similar way, i.e. by implementing the interface org.openhealthtools.ihe.atna.auditor.queue.AuditMessageQueue and installing the corresponding class instance via AuditorModuleContext.getContext().setQueue(myQueue).
These settings will affect all auditors, because the auditor module context is a singleton.
URL Parameters' Summary
The following table gives an overview of all URL parameters defined for IPF XDS endpoints.
| Name | Type | Default value | Transactions | Side | Short description |
|---|---|---|---|---|---|
| secure | boolean | false | all except ITI-17 | client only for XDS.a+b; both server and client for PIX/PDQ |
whether Transport Layer Security mechanisms should be applied when sending messages |
| audit | boolean | true | all except ITI-17 | both service and client | whether ATNA auditing should be performed by the corresponding party |
| allowIncompleteAudit | boolean | false | all except ITI-17 | both service and client | whether incomplete audit records should be sent to the ATNA repository as well |
| soap11 | boolean | false | XDS.b | client only | whether requests should be sent using SOAP 1.1 instead of SOAP 1.2 |
| codec | String | "hl7codec" | PIX/PDQ | both service and client | name of HL7 codec factory bean |