I have recently worked on an interesting use case to integrate JDV with a SOAP Webservice which exposes WS-Addressing behavior via SOAP headers and requires a 2-way SSL. The use case stems from some strict regulations in the host country which prevent direct access to data sensitive systems and any access has to be via a web service, authenticated and encrypted. The following example showcases the configurations required and can be found in github. Installation Guide - Red Hat Customer Portal

Setup JDV Server

TEIID Username : teiidUser 

TEIID Password : xxxx

Install JBDS 9.1.0
Setup JDV Design Environment (TEIID Designer)

Setup EAP Server with two-way SSL authentication

(see JDVTooling/jdv-jax-wsa-ssl-example/ssl-materials at master · skoussou/JDVTooling · GitHub folder)

All the client and server keystores are included in the folders

  • JDV-SSL-CLient
  • EAP-SSL-Server

JDVTooling/READEME-Setup-Server-Client-SSL-Keystores-JBoss-EAP-SSL-Config.md at master · skoussou/JDVTooling · GitHub  describes the setup

Setup JDV Project

Create Datasource Connection to SOAP Web Service

In JBDS perform the following steps:

  1. Open the “Data Source Explorer View” via menu Window → Show View → Other → Data Source Explorer View

  2. Choose “Teiid Importer Connections” right click New → Web Services Data Source (SOAP) define name eg. WSAAddressing (SOAP) → URL → (URL where the WSDL can be found) + Security Type (HNone) → Test Connection → Select the Endpoint → Finish

IMPORTANT: The WSDL exposed does not seem to be possible to be imported via the URL (possibly due to 2-way SSL) in TEIID Designer. As a result in the above instructions two parts have to be different.

a) From the browser downlad the WSDL xml saving as AddressingService.wsdl and then use instead of URL the FileSystem and locate the WSDL (AddressingService.wsdl)

b) Do not press Testing as it will fail and you will have to start from the beginning the process.

Create Source & Virtual Base Layer Models to SOAP Webservice

JDV best practices define the the Views created inside the engine are abstracted from the physical view of the datasource so that in the case that in the future the PHYSICAL source changes the enterprise and federated queries remain the same. Therefore, we always create one Source Model for each datasource and one Virtual Base Layer (with potentially more built on top of it as we further abstract the queries and combine Views from multiple datasources).

On the Source Models folder inside the JBDS Teiid Project (if no folder then create) Right click → Import → Web Service Source >> Source And View Model (SOAP) → In the next page choose

  • Connection Profile: WSAAddressing (SOAP) which we created above

  • Validate the WSDL

  • Service Mode: MESSAGE (as the web service we connect to requires WS-A headers we had to define and send the whole<soap:envelope> via the MODELs not just the payload

  • Select the Operation or Operations which we will connect to (think of these as Database Names)

Proceed through the next screens without changes unless you desire to until you reach “Procedure Definition” where you will selected for REQUEST the fields from the elements required for the request and the response”. We have selected

REQUEST: sayHello element

RESPONSE:  return

Then in the resulting Virtual Base Layer View you can define the appropriate query to provide in the Request the WS-A headers (see Appendix C – SOA-P Request) and additional request fields (the additional you need to add them manually to the model request).

Important: The headers are not defined in the default query despite earlier selecting MESSAGE as the option you will have to create them as the example request shows.

SayHello_request
BEGIN

SELECT XMLELEMENT(NAME "soap:Envelope", XMLNAMESPACES('http://schemas.xmlsoap.org/soap/envelope/' AS soap, 'http://www.jboss.org/jbossws/ws-extensions/wsaddressing' AS tns, 'http://www.w3.org/2005/08/addressing' AS wsa), 
XMLELEMENT(NAME "soap:Header", XMLELEMENT(NAME"wsa:MessageID", AddressingServiceView_4.sayHello_request.MessageID), XMLELEMENT(NAME "wsa:To", AddressingServiceView_4.sayHello_request."To"),XMLELEMENT(NAME "wsa:ReplyTo", AddressingServiceView_4.sayHello_request.ReplyTo), 
XMLELEMENT(NAME "wsa:Action",AddressingServiceView_4.sayHello_request.Action)), XMLELEMENT(NAME "soap:Body", XMLELEMENT(NAME "tns:sayHello",AddressingServiceView_4.sayHello_request.sayHello))) AS xml_out;

END
SayHello_response
BEGIN

SELECT t.* FROM XMLTABLE(XMLNAMESPACES('http://www.jboss.org/jbossws/ws-extensions/wsaddressing' AS tns,'http://schemas.xmlsoap.org/soap/envelope/' AS soap), '/soap:Envelope' PASSING 
AddressingServiceView_4.sayHello_response.xml_in COLUMNS "return"string PATH '/soap:Body/tns:sayHelloResponse/return') AS t;

END
Overall query SayHello
BEGIN

SELECT t.* FROM TABLE(EXEC AddressingServiceView_4.sayHello_request(AddressingServiceView_4.sayHello.sayHello,AddressingServiceView_4.sayHello.MessageID, AddressingServiceView_4.sayHello."To", 
AddressingServiceView_4.sayHello.ReplyTo,AddressingServiceView_4.sayHello.Action)) AS request, TABLE(EXEC AddressingService_4.invoke(binding => 'SOAP11', action => '', request =>request.xml_out, 
endpoint => null, stream => TRUE)) AS response, TABLE(EXEC AddressingServiceView_4.sayHello_response(response.result)) AS t;

END
Resources

Configure a JDV Web Service Datasource connection with 2-way SSL JDV to the SOAP Webservice Endpoint

JDV Utilizes Resource Adapters on the underlying JBoss EAP server (based on JEE specification) to connect to disparate technologies via defining configuration of the adapter on the server and making the usage of it available via a JNDI (Naming Directory) to the VDBs. The documentation which defines how to configure the resource adapter for a web service datasource can be found at https://teiid.gitbooks.io/documents/content/admin/Web_Service_Data_Sources.html

see JDVTooling/standalone.xml at master · skoussou/JDVTooling · GitHub  for an example

Resource Adapter configuration for connection to SOAP Webservice with HTTP Basic Authentication and SSL Connection
<subsystem xmlns="urn:jboss:domain:resource-adapters:1.1">

<resource-adapters>

<resource-adapter id="AddressingService_4">

<module slot="main" id="org.jboss.teiid.resource-adapter.webservice"/>

<transaction-support>NoTransaction</transaction-support>

<connection-definitions>

<connection-definition class-name="org.teiid.resource.adapter.ws.WSManagedConnectionFactory" jndi-name="java:/AddressingService_4" enabled="true" pool-name="AddressingService_4">

<config-property name="SecurityType">

None

</config-property>

<config-property name="EndPoint">

https://localhost:8543/jboss-jaxws-addressing/AddressingService

</config-property>

<config-property name="ConfigFile">

/home/stkousso/Stelios/sw10/JDV/Distros/jboss-eap-6.4/standalone/configuration/ssl-jbossws-cxf.xml

</config-property>

</connection-definition>

</connection-definitions>

</resource-adapter>

</resource-adapters>

The ConfigFile provides the ability for the connector to utilize a technology called CXF to produce the appropriate protocol settings. In the case above the two settings are

  • HTTP Basic Authentication via a service user (ie. not pass through)

  • 2-way SSL

see JDVTooling/ssl-jbossws-cxf.xml at master · skoussou/JDVTooling · GitHub for an example

ssl-jbossws-cxf.xml: CXF Configuration for 2-way SSL
<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:sec="http://cxf.apache.org/configuration/security"

xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"

xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"

xmlns:jaxws2="http://cxf.apache.org/jaxws"

xsi:schemaLocation="http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

<jaxws2:client name="http://localhost:31000"

createdFromAPI="true">

<jaxws2:features>

<bean class="org.apache.cxf.feature.LoggingFeature"/>

</jaxws2:features>

</jaxws2:client>

<http-conf:conduit name="*.http-conduit">

<!--NOTE you can limit this to the service by giving a more restrictive conduit name

http-conf:conduit name="https://ws-gateway-cert-qs.wob.vw.vwg/services"-->

<!-- WARNING ! disableCNcheck=true should NOT be used in production disableCNcheck="true" but instead the domain of the certificate should match the endpoint of the exposed web serice-->

<http-conf:authorization>

<!--sec:UserName>DWSUCDQ</sec:UserName>

<sec:Password>xxxxxxxxxx</sec:Password-->

<sec:AuthorizationType>None</sec:AuthorizationType>

</http-conf:authorization>

-->

<http-conf:client ConnectionTimeout="120000" ReceiveTimeout="240000"/>

<http-conf:tlsClientParameters disableCNCheck="true" secureSocketProtocol="SSL" >

<!-- Client Trustore with server certificate to check against the server provided

<sec:trustManagers>

<sec:keyStore type="JKS" password="[CLIENT TRUSTORE KEYSTORE PASSWORD]" file="../standalone/configuration/client_truststore.jks"/>

<!-- Client Certificate to be provided for the 2-way SSL handshake

</sec:trustManagers>

<sec:keyManagers keyPassword="1WPS2N0Q">

<sec:keyStore type="PKCS12" password="KEYSTORE PASSWORD" file="../standalone/configuration/DWSUCDQ.p12"/>

</sec:keyManagers>

</http-conf:tlsClientParameters>

</http-conf:conduit>

</beans>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:sec="http://cxf.apache.org/configuration/security"

xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"

xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"

xsi:schemaLocation="http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd">

<jaxws2:client name="http://localhost:31000"

createdFromAPI="true">

<jaxws2:features>

<bean class="org.apache.cxf.feature.LoggingFeature"/>

</jaxws2:features>

</jaxws2:client>

<http-conf:conduit name="*.http-conduit">

<!--NOTE you can limit this to the service by giving a more restrictive conduit name

http-conf:conduit name="https://localhost:8543/jboss-jaxws-addressing/AddressingService"-->

<!-- WARNING ! disableCNcheck=true should NOT be used in production disableCNcheck="true" -->

<http-conf:client ConnectionTimeout="120000" ReceiveTimeout="240000"/>

<http-conf:tlsClientParameters disableCNCheck="true" secureSocketProtocol="SSL" >

<sec:trustManagers>

<sec:keyStore type="JKS" password="mypass" file="../standalone/configuration/client.jks"/>

</sec:trustManagers>

<sec:keyManagers keyPassword="sslworkshop">

<sec:keyStore type="JKS" password="sslworkshop" file="../standalone/configuration/clientauth_ks.jks"/>

</sec:keyManagers>

</http-conf:tlsClientParameters>

</http-conf:conduit>

</beans>

IMPORTANT: The JDV server MUST be started with standalone.bat -Dhttps.protocols=TLSv1

Resources:

For the creation of the keystores read the READEME-Setup-Server-Client-SSL-Keystores-JBoss-EAP-SSL-Config.md

The VDB

In the project we created a Folder VirtualDatabase and in there we used the modelling menu to create a new VDB named WSA-Models.vdb chooing the choosing

  • Source Model: AddressingService_4
  • Virtual Base Model: AddressingServiceView_4
  • and very important the translator name AddressingService_4_ws which provides overrides on sending SOAP messages via MESSAGE and not PAYLOAD in comparison to the translator provided by default in the JDV Server.
  • Relies on the resource adapter above with JNDI Name: "java:/AddressingService_4"
  • To expose the WSA-Models VDB via JDBC the following setting is required on the datasources subsystem
VDB Datasource
<datasource jndi-name="java:/WSA-Models" pool-name="WSA-Models" enabled="true">

<connection-url>jdbc:teiid:WSA-Models@mm://localhost:31000</connection-url>

<driver>teiid</driver>

<security>

<user-name>teiidUser</user-name>

<password>Password630!</password>

</security>

</datasource>
  • Create a TEIID Connection against the server via an SQL client with the TEIID JDBC Driver and execute the query in Teiid-JDBC-Test-Queries.sql any changes to the ssl-jbossws-cxf.xml (eg. such as password or file names) will result in the 2-way SSL to fail

 

Patch the JDV Server

Due to a change in the behavior of one of the libraries JDV depends on to create SOAP messages the a JIRA https://issues.jboss.org/browse/TEIID-4755 was created and a patch provided by the engineering team. To apply the JIRA in the JDV Home directory follow the path modules/system/layers/dv/org/jboss/teiid/translator/ws/main and

a) place the translator-ws-8.12.9.6_3.jar that accompanies this report

b) replace the module.xml with

module.xml
<?xml version="1.0" encoding="UTF-8"?>

<module xmlns="urn:jboss:module:1.0" name="org.jboss.teiid.translator.ws">

<properties>

<property name="jboss.api" value="private"/>

</properties>

<resources>

<!-- resource-root path="translator-ws-8.12.5.redhat-8.jar" /-->

<!-- Patched to correct ClassCastException -->

<resource-root path="translator-ws-8.12.9.6_3.jar" />

<!-- Insert resources here -->

</resources>

<dependencies>

<module name="javax.xml.ws.api"/>

<module name="javax.api"/>

<module name="javax.resource.api"/>

<module name="org.jboss.teiid.common-core" />

<module name="org.jboss.teiid.api" />

<module name="org.jboss.teiid" />

<module name="javax.wsdl4j.api"/>

<module name="org.springframework.spring" optional="true"/>

</dependencies>

</module>

This will be added in teiid 9.2 & 9.3


Connect with Red Hat Services

Learn more about Red Hat Consulting
Learn more about Red Hat Training
Learn more about Red Hat Certification
Subscribe to the Training Newsletter
Follow Red Hat Services on Twitter
Follow Red Hat Open Innovation Labs on Twitter
Like Red Hat Services on Facebook
Watch Red Hat Training videos on YouTube
Follow Red Hat Certified Professionals on LinkedIn
Creative Commons License