Implementing an Adapter for CONNECT Adoption
CONNECT is broken up into various layers, and in order to adopt CONNECT into your existing infrastructure, you may need to implement one or more adapters tailored to your needs. This can be done in a number of ways. The easiest and most common would be to hook the existing web service proxies up to point to a URL of the implementing adapter. Another way would be to implement the adapter in Java as a spring bean, bundle up the adapter with the CONNECT EAR deployment, and change the bean alias to your new adapter.
CONNECT also provides reference adapters for Java, Secure, and Unsecured implementations which can be found in its respective Adapter project in the source code repository. As an example: Product/Production/Adapters/DocumentQuery_a0 for the Document Query reference adapters.
Webservice Adapter Option
CONNECT comes with two proxies for using adapters: Secured and Unsecured. Secured interface sends WS-Security header and SAML assertion in soap header while the unsecured interface do not send and process WS-Security header and SAML assertions. As these proxies call a potentially externally housed webservice, this means that the implementation does not have to be a Java based application and will work as long as they conform to the adapter requirement specs.
The following steps are needed in order to correctly adopt the webservice option:
- Create a webservice and implement the appropriate WSDL for that adapter. These can be found in the CONNECT Webservices repository. As an example: DocumentQuery/src/main/resources/wsdl/AdapterDocQuery.wsdl for the Document Query Adapter.
Change the InternalExchangeInfo.xml listing to point to your new webservice. Please note that you only need to change the respective Secured / Unsecured URL depending on which implementation you chose. Both Secured and Unsecured examples are shown below:
<ns2:endpoint> <ns2:name>adapterdocquery</ns2:name> <ns2:endpointConfigurationList> <ns2:endpointConfiguration> <ns2:url>http://localhost:8080/MyNewService/MyUnsecuredDocQueryAdapter</ns2:url> <ns2:version>LEVEL_a0</ns2:version> </ns2:endpointConfiguration> </ns2:endpointConfigurationList> </ns2:endpoint> <ns2:endpoint> <ns2:name>adapterdocquerysecured</ns2:name> <ns2:endpointConfigurationList> <ns2:endpointConfiguration> <ns2:url>https://localhost:8181/MyNewService/MySecuredDocQueryAdapter</ns2:url> <ns2:version>LEVEL_a0</ns2:version> </ns2:endpointConfiguration> </ns2:endpointConfigurationList> </ns2:endpoint>
 Update the respective proxy file to use one of the provided web service proxies. Secured Proxy should be used for Secured Services, and Unsecured for Unsecured services. Note that you only need to change the Alias for the service. You do not need to modify the already existing beans contained in the file. In the example below we use the Secured adapter bean.
<!-- Beans defined for adapterdocquery --> <alias alias="adapterdocquery" name="adapterdocquerywssecured" />
Java Adapter Option
Important!
While the CONNECT team does not recommend this option, it may provide more secure and performant adapters which may interface directly with CONNECT.
There is currently no standard when it comes to Java implementations as the use cases and availability of certain technology stacks will differ between adopters. A sample Java adapter and its respective proxy have been included in the CONNECT code base and can be used as a base for your implementation. While not recommended, the simplest way to introduce a Java adapter is to modify the Java reference adapter directly and bundle it with the CONNECT EAR. A more elegant approach is to implement a new proxy and implementation entirely. As the project uses Spring Injection for its services and adapters, the only requirement is that the new bean for your adapter and proxy can be found within the Spring Context for injection. In order to preserve the Event and Failure logging functionality, ensure you have marked your java entry method with the @AdapterDelegationEvent annotation and provided the respective builder classes.
For reference, all the configurable Java classes have been listed below. Entity proxies have also been included as the same steps apply for implementing these interfaces:
Service / Feature | Component Type | Java Class |
---|---|---|
MPI | Adapter | gov.hhs.fha.nhinc.mpi.adapter.component.PatientChecker |
MPI | Adapter | gov.hhs.fha.nhinc.mpi.adapter.component.proxy.AdapterComponentMpiProxyJavaImpl |
MPI | Adapter | gov.hhs.fha.nhinc.mpi.adapter.proxy.AdapterMpiProxyJavaImpl |
Redaction Engine | Adapter | gov.hhs.fha.nhinc.redactionengine.adapter.proxy.AdapterRedactionEngineProxyJavaImpl |
Admin Distribution | Adapter | gov.hhs.fha.nhinc.admindistribution.adapter.proxy.AdapterAdminDistributionProxyJavaImpl |
Admin Distribution | Entity | gov.hhs.fha.nhinc.admindistribution.entity.proxy.EntityAdminDistributionProxyJavaImpl |
Audit Query Logger | Entity | gov.hhs.fha.nhinc.auditquerylog.nhinc.proxy.AuditQueryLogProxyJavaImpl |
Audit Repository | Entity | gov.hhs.fha.nhinc.auditrepository.nhinc.proxy.AuditRepositoryProxyJavaImpl |
CORE X12 Document Submission | Adapter | gov.hhs.fha.nhinc.corex12.ds.genericbatch.request.adapter.proxy.AdapterX12BatchRequestProxyJavaImpl |
CORE X12 Document Submission | Adapter | gov.hhs.fha.nhinc.corex12.ds.genericbatch.response.adapter.proxy.AdapterX12BatchResponseProxyJavaImpl |
CORE X12 Document Submission | Adapter | gov.hhs.fha.nhinc.corex12.ds.realtime.adapter.proxy.AdapterX12RealTimeProxyJavaImpl |
Document Data Submission (Pilot) | Adapter | gov.hhs.fha.nhinc.docdatasubmission.adapter.proxy.AdapterDocDataSubmissionProxyJavaImp |
Document Data Submission (Pilot) | Entity | gov.hhs.fha.nhinc.docdatasubmission.entity.proxy.EntityDocDataSubmissionProxyJavaImpl |
Document Query | Entity | gov.hhs.fha.nhinc.docquery.entity.proxy.EntityDocQueryProxyJavaImpl |
Document Query | Adapter | gov.hhs.fha.nhinc.docquery.adapter.proxy.AdapterDocQueryProxyJavaImpl |
Document Registry | Adapter | gov.hhs.fha.nhinc.docregistry.adapter.proxy.AdapterComponentDocRegistryProxyJavaImpl |
Document Retrieve | Adapter | gov.hhs.fha.nhinc.docretrieve.adapter.proxy.AdapterDocRetrieveProxyJavaImpl |
Document Retrieve | Entity | gov.hhs.fha.nhinc.docretrieve.entity.proxy.EntityDocRetrieveProxyJavaImpl |
Document Repository | Adapter | gov.hhs.fha.nhinc.docrepository.adapter.proxy.AdapterComponentDocRepositoryProxyJavaImpl |
Document Submission | Adapter | gov.hhs.fha.nhinc.docsubmission.adapter.deferred.request.error.proxy.AdapterDocSubmissionDeferredRequestErrorProxyJavaImpl |
Document Submission | Adapter | gov.hhs.fha.nhinc.docsubmission.adapter.deferred.request.proxy.AdapterDocSubmissionDeferredRequestProxyJavaImpl |
Document Submission | Adapter | gov.hhs.fha.nhinc.docsubmission.adapter.component.deferred.request.proxy.AdapterComponentDocSubmissionRequestProxyJavaImpl |
Document Submission | Entity | gov.hhs.fha.nhinc.docsubmission.entity.deferred.request.proxy.EntityDocSubmissionDeferredRequestProxyJavaImpl |
Document Submission | Adapter | gov.hhs.fha.nhinc.docsubmission.adapter.component.deferred.response.proxy.AdapterComponentDocSubmissionResponseProxyJavaImpl |
Document Submission | Adapter | gov.hhs.fha.nhinc.docsubmission.adapter.deferred.response.proxy.AdapterDocSubmissionDeferredResponseProxyJavaImpl |
Document Submission | Entity | gov.hhs.fha.nhinc.docsubmission.entity.deferred.response.proxy.EntityDocSubmissionDeferredResponseProxyJavaImpl |
Document Submission | Adapter | gov.hhs.fha.nhinc.docsubmission.adapter.proxy.AdapterDocSubmissionProxyJavaImpl |
Document Submission | Adapter | gov.hhs.fha.nhinc.docsubmission.adapter.component.proxy.AdapterComponentDocSubmissionProxyJavaImpl |
Document Submission | Entity | gov.hhs.fha.nhinc.docsubmission.entity.proxy.EntityDocSubmissionProxyJavaImpl |
Patient Discovery | Adapter | gov.hhs.fha.nhinc.patientdiscovery.adapter.deferred.request.error.proxy.AdapterPatientDiscoveryDeferredReqErrorProxyJavaImpl |
Patient Discovery | Adapter | gov.hhs.fha.nhinc.patientdiscovery.adapter.deferred.request.proxy.AdapterPatientDiscoveryDeferredReqProxyJavaImpl |
Patient Discovery | Adapter | gov.hhs.fha.nhinc.patientdiscovery.adapter.deferred.request.queue.proxy.AdapterPatientDiscoveryAsyncReqQueueProxyJavaImpl |
Patient Discovery | Entity | gov.hhs.fha.nhinc.patientdiscovery.entity.deferred.request.proxy.EntityPatientDiscoveryDeferredRequestProxyJavaImpl |
Patient Discovery | Adapter | gov.hhs.fha.nhinc.patientdiscovery.adapter.deferred.response.proxy.AdapterPatientDiscoveryDeferredRespProxyJavaImpl |
Patient Discovery | Entity | gov.hhs.fha.nhinc.patientdiscovery.entity.deferred.response.proxy.EntityPatientDiscoveryDeferredResponseProxyJavaImpl |
Patient Discovery | Adapter | gov.hhs.fha.nhinc.patientdiscovery.adapter.proxy.AdapterPatientDiscoveryProxyJavaImpl |
Patient Discovery | Entity | gov.hhs.fha.nhinc.patientdiscovery.entity.proxy.EntityPatientDiscoveryProxyJavaImpl |
Patient Location Query (Pilot) | Entity | gov.hhs.fha.nhinc.patientlocationquery.entity.proxy.EntityPatientLocationQueryProxyJavaImpl |
Patient Location Query (Pilot) | Adapter | gov.hhs.fha.nhinc.patientlocationquery.adapter.proxy.AdapterPatientLocationQueryProxyJavaImpl |
Policy Engine | Adapter | gov.hhs.fha.nhinc.policyengine.adapter.proxy.PolicyEngineProxyJavaImpl |
Policy Engine | Adapter | gov.hhs.fha.nhinc.policyengine.adapter.orchestrator.proxy.AdapterPolicyEngineOrchProxyJavaImpl |
Policy Engine | Adapter | gov.hhs.fha.nhinc.policyengine.adapter.pep.proxy.AdapterPEPProxyJavaImpl |
Example: Document Query skeleton injection
The following will be a step by step walk through on how to inject a custom implementation of the Document Query adapter. The adapter will do nothing but return an empty response - as implementation is up to you, the adopter. We will be adding a new project to keep your adapter code isolated from CONNECT core code. There are a few pitfalls to take note of during this example - one of which is a circular dependency which may complicate things later on.Â
Note: This circular dependency can easily be solved by extracting the adapter interfaces you wish to use into a shared maven dependency rather than using the *Core JAR files as the dependency. This was not introduced into the main branch due to Legacy constraints.
 Document Query Adapter - Maven POM
A bare bones Maven POM file is provided below:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <artifactId>MyCustomAdapter</artifactId> <groupId>com.example</groupId> <name>CUSTOM Adapter - ${project.artifactId}</name> <version>1.0.0</version> <packaging>jar</packaging> <modelVersion>4.0.0</modelVersion> <properties> <spring.version>4.1.9.RELEASE</spring.version> </properties> <dependencies> <!-- CONNECT Modules / Web Services --> <dependency> <groupId>org.connectopensource</groupId> <artifactId>CONNECTCoreLib</artifactId> <version>5.3.0</version> </dependency> <dependency> <groupId>org.connectopensource</groupId> <artifactId>DocumentQueryCore</artifactId> <version>5.3.0</version> </dependency> <dependency> <groupId>org.connectopensource</groupId> <artifactId>CONNECTCommonTypesLib</artifactId> <version>5.3.0</version> </dependency> <dependency> <groupId>org.connectopensource</groupId> <artifactId>DocumentQueryWebservices</artifactId> <version>5.3.0</version> </dependency> <!-- Logging --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!-- Spring Framework --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> </dependencies> <build> <finalName>${project.artifactId}</finalName> </build> </project>
Document Query Adapter - Example Class
As we will be demonstrating how to implement the Document Query adapter, we will need to use the Adapter Proxy for document query - AdapterDocQueryProxy in this case. Take note the @AdapterDelegationEvent annotation on the method. This is used by failure logging and event logging and must be present on your Java adapter implementations. Failure to do so may result in raised exceptions not being caught and logged correctly, as well as incomplete/corrupted logging of the invocation of CONNECT. You may use the reference Java adapters for examples on the builder classes regarding the Event aspect.
package com.example.mycustomadapter import gov.hhs.fha.nhinc.aspect.AdapterDelegationEvent; import gov.hhs.fha.nhinc.common.nhinccommon.AssertionType; import gov.hhs.fha.nhinc.docquery.adapter.proxy.AdapterDocQueryProxy; import gov.hhs.fha.nhinc.docquery.aspect.AdhocQueryRequestDescriptionBuilder; import gov.hhs.fha.nhinc.docquery.aspect.AdhocQueryResponseDescriptionBuilder; import oasis.names.tc.ebxml_regrep.xsd.query._3.AdhocQueryRequest; import oasis.names.tc.ebxml_regrep.xsd.query._3.AdhocQueryResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @Component public class MyDocQueryAdapter implements AdapterDocQueryProxy{ private static final Logger LOG = LoggerFactory.getLogger(MyDocQueryAdapter.class); @AdapterDelegationEvent(beforeBuilder = AdhocQueryRequestDescriptionBuilder.class, afterReturningBuilder = AdhocQueryResponseDescriptionBuilder.class, serviceType = "Document Query", version = "LEVEL_a0") public AdhocQueryResponse respondingGatewayCrossGatewayQuery(AdhocQueryRequest msg, AssertionType assertion) { LOG.info("We called from inside our adapter and you have successfully injected your Java adapter into the CONNECT code"); return new AdhocQueryResponse(); } }
Linking it together
Once you have implemented your custom adapter, your new project must be put in as a dependency for the service you are implementing. This is because your new beans (Created by the proxy definitions) will be in the same shared spring context as the rest of the other beans in the service. In the following snippet, we have added the "com.example" group ID and "MyCustomAdapter" artifact you have built earlier and installed into your local maven repository.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>org.connectopensource</groupId> <artifactId>Services</artifactId> <version>5.3.0</version> </parent> <artifactId>DocumentQueryCore</artifactId> <name>CONNECT Document Query Core</name> <packaging>jar</packaging> <modelVersion>4.0.0</modelVersion> <dependencies> <!-- Java EE APIs --> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> </dependency> <dependency> <groupId>com.example</groupId> <artifactId>MyCustomAdapter</artifactId> <version>1.0.0</version> </dependency> <!-- CONNECT Modules / Web Services --> <dependency> <groupId>org.connectopensource</groupId> <artifactId>CONNECTCoreLib</artifactId> <version>${project.parent.version}</version> </dependency> <dependency> <groupId>org.connectopensource</groupId> <artifactId>AuditRepositoryCore</artifactId> <version>${project.parent.version}</version> </dependency> <dependency> <groupId>org.connectopensource</groupId> <artifactId>PatientCorrelationCore</artifactId> <version>${project.parent.version}</version> </dependency> ...
Once this is done, you may then build CONNECT. At this point in time, you should not experience any validation suite failures as your code is not currently configured to be used. Should you encounter any build issues, please double check you have correctly performed the previous instructions.
Once you have compiled CONNECT and have the CONNECT EAR generated, you may begin to deploy it to your server of choice. You will also need to configure the corresponding Proxy files in your CONNECT Properties folder. In the above example, we were adding a Document Query adapter proxy, so we would change the following lines of DocumentQueryProxyConfig.xml:
<!-- Beans defined for adapterdocquery --> <alias alias="adapterdocquery" name="adapterdocquerycustom" /> ... ... ... <bean lazy-init="true" class="com.example.mycustomadapter.MyDocQueryAdapter" id="adapterdocquerycustom" name="adapterdocquerycustom"> <meta key="impltype" value="java"/> </bean> ... ... ...
Here, we set the "adapterdocquery" bean alias to our newly defined bean named "adapterdocquerycustom" and specified the class we created.
Testing everything
Finally, start your server with the deployed EAR and configured proxy files and run validation suite from SOAP UI. If you have implemented everything, you should see all the tests pass. You may then run the regression suite as well to ensure you have satisfied the criteria of the implementation.