Skip to content

Commit

Permalink
TEIID-4755: WS SOAP Response with WS-A Headers results in
Browse files Browse the repository at this point in the history
ClassCastException (Using the DOM based return in MESSAGE mode as CXF
does not allow StAX based Source)

# Conflicts:
#	build/kits/jboss-as7/overlay/docs/teiid/teiid-releasenotes.html
  • Loading branch information
rareddy authored and shawkins committed May 19, 2017
1 parent 80c16c1 commit 3f71a69
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 16 deletions.
Expand Up @@ -22,6 +22,10 @@

package org.teiid.translator.ws;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.sql.SQLException;
Expand All @@ -30,15 +34,20 @@
import java.util.List;

import javax.xml.stream.XMLStreamException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service.Mode;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.handler.MessageContext;

import org.teiid.core.types.InputStreamFactory;
import org.teiid.core.types.SQLXMLImpl;
import org.teiid.core.types.XMLType;
import org.teiid.core.types.XMLType.Type;
Expand All @@ -63,7 +72,7 @@ public class WSProcedureExecution implements ProcedureExecution {
RuntimeMetadata metadata;
ExecutionContext context;
private Call procedure;
private StAXSource returnValue;
private Source returnValue;
private WSConnection conn;
private WSExecutionFactory executionFactory;

Expand All @@ -78,29 +87,34 @@ public WSProcedureExecution(Call procedure, RuntimeMetadata metadata, ExecutionC
this.executionFactory = executionFactory;
}

@SuppressWarnings("unchecked")
public void execute() throws TranslatorException {
List<Argument> arguments = this.procedure.getArguments();

String style = (String)arguments.get(0).getArgumentValue().getValue();
String action = (String)arguments.get(1).getArgumentValue().getValue();
XMLType docObject = (XMLType)arguments.get(2).getArgumentValue().getValue();
StAXSource source = null;
Source source = null;
try {
source = convertToSource(docObject);
Class type = StAXSource.class;
if (executionFactory.getDefaultServiceMode() == Mode.MESSAGE) {
type = DOMSource.class;
}

source = convertToSource(type, docObject);
String endpoint = (String)arguments.get(3).getArgumentValue().getValue();

if (style == null) {
style = executionFactory.getDefaultBinding().getBindingId();
} else {
try {
Binding type = Binding.valueOf(style.toUpperCase());
style = type.getBindingId();
style = Binding.valueOf(style.toUpperCase()).getBindingId();
} catch (IllegalArgumentException e) {
throw new TranslatorException(WSExecutionFactory.UTIL.getString("invalid_invocation", Arrays.toString(Binding.values()))); //$NON-NLS-1$
}
}

Dispatch<StAXSource> dispatch = conn.createDispatch(style, endpoint, StAXSource.class, executionFactory.getDefaultServiceMode());
Dispatch dispatch = conn.createDispatch(style, endpoint, type, executionFactory.getDefaultServiceMode());

if (Binding.HTTP.getBindingId().equals(style)) {
if (action == null) {
Expand Down Expand Up @@ -133,7 +147,7 @@ public void execute() throws TranslatorException {
// JBoss Native DispatchImpl throws exception when the source is null
source = new StAXSource(XMLType.getXmlInputFactory().createXMLEventReader(new StringReader("<none/>"))); //$NON-NLS-1$
}
this.returnValue = dispatch.invoke(source);
this.returnValue = (Source) dispatch.invoke(source);
} catch (SQLException e) {
throw new TranslatorException(e);
} catch (WebServiceException e) {
Expand All @@ -145,12 +159,12 @@ public void execute() throws TranslatorException {
}
}

private StAXSource convertToSource(SQLXML xml) throws SQLException {
if (xml == null) {
return null;
}
return xml.getSource(StAXSource.class);
}
private Source convertToSource(Class<? extends Source> T, SQLXML xml) throws SQLException {
if (xml == null) {
return null;
}
return xml.getSource(T);
}

@Override
public List<?> next() throws TranslatorException, DataNotAvailableException {
Expand All @@ -160,14 +174,33 @@ public List<?> next() throws TranslatorException, DataNotAvailableException {
@Override
public List<?> getOutputParameterValues() throws TranslatorException {
Object result = returnValue;
if (returnValue != null && procedure.getArguments().size() > 4
if (returnValue != null && (returnValue instanceof StAXSource) && procedure.getArguments().size() > 4
&& procedure.getArguments().get(4).getDirection() == Direction.IN
&& Boolean.TRUE.equals(procedure.getArguments().get(4).getArgumentValue().getValue())) {
SQLXMLImpl sqlXml = new StAXSQLXML(returnValue);
SQLXMLImpl sqlXml = new StAXSQLXML((StAXSource)returnValue);
XMLType xml = new XMLType(sqlXml);
xml.setType(Type.DOCUMENT);
result = xml;
}
} else if (returnValue != null && returnValue instanceof DOMSource){
final DOMSource xmlSource = (DOMSource) returnValue;
SQLXMLImpl sqlXml = new SQLXMLImpl(new InputStreamFactory() {
@Override
public InputStream getInputStream() throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Result outputTarget = new StreamResult(outputStream);
try {
TransformerFactory.newInstance().newTransformer()
.transform(xmlSource, outputTarget);
} catch (Exception e) {
throw new IOException(e);
}
return new ByteArrayInputStream(outputStream.toByteArray());
}
});
XMLType xml = new XMLType(sqlXml);
xml.setType(Type.DOCUMENT);
result = xml;
}
return Arrays.asList(result);
}

Expand Down
Expand Up @@ -33,6 +33,8 @@

@SuppressWarnings("nls")
public class AdminUtil {

public static final int MANAGEMENT_PORT = 9990;

static void cleanUp(Admin admin) throws AdminException {
//TODO: cleanup when as supports it
Expand Down
@@ -0,0 +1,110 @@
/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/

package org.teiid.arquillian;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Collection;
import java.util.Properties;

import org.jboss.arquillian.junit.Arquillian;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.teiid.adminapi.Admin;
import org.teiid.adminapi.AdminException;
import org.teiid.adminapi.VDB;
import org.teiid.adminapi.VDB.Status;
import org.teiid.adminapi.jboss.AdminFactory;
import org.teiid.core.util.UnitTestUtil;
import org.teiid.jdbc.TeiidDriver;

@RunWith(Arquillian.class)
@SuppressWarnings("nls")
public class IntegrationTestSOAPWebService {

private Admin admin;

@Before
public void setup() throws Exception {
admin = AdminFactory.getInstance().createAdmin("localhost", AdminUtil.MANAGEMENT_PORT, "admin",
"admin".toCharArray());
}

@After
public void teardown() throws AdminException {
AdminUtil.cleanUp(admin);
admin.close();
}

@Test
public void testVDBDeployment() throws Exception {
Collection<?> vdbs = admin.getVDBs();
assertTrue(vdbs.isEmpty());

assertTrue(admin.getDataSourceTemplateNames().contains("webservice"));
String raSource = "web-ds";
assertFalse(admin.getDataSourceNames().contains(raSource));

admin.deploy("addressing-service.war", new FileInputStream(UnitTestUtil.getTestDataFile("addressing-service.war")));

Properties p = new Properties();
p.setProperty("class-name", "org.teiid.resource.adapter.ws.WSManagedConnectionFactory");
p.setProperty("EndPoint", "http://localhost:8080/jboss-jaxws-addressing/AddressingService");

admin.createDataSource(raSource, "webservice", p);

assertTrue(admin.getDataSourceNames().contains(raSource));

admin.deploy("soapsvc-vdb.xml",new FileInputStream(UnitTestUtil.getTestDataFile("soapsvc-vdb.xml")));
vdbs = admin.getVDBs();
assertFalse(vdbs.isEmpty());

VDB vdb = admin.getVDB("WSMSG", 1);
AdminUtil.waitForVDBLoad(admin, "WSMSG", 1, 3);

vdb = admin.getVDB("WSMSG", 1);
assertTrue(vdb.isValid());
assertTrue(vdb.getStatus().equals(Status.ACTIVE));

Connection conn = TeiidDriver.getInstance().connect("jdbc:teiid:WSMSG@mm://localhost:31000;user=user;password=user;", null);
Statement stmt = conn.createStatement();
String sql = "SELECT *\n" +
"FROM ADDRESSINGSERVICE.SAYHELLO\n" +
"WHERE MESSAGEID = 'UUID-100' AND SAYHELLO = 'Teiid'\n" +
"AND ADDRESSINGSERVICE.SAYHELLO.To = 'http://www.w3.org/2005/08/addressing/anonymous'\n" +
"AND ADDRESSINGSERVICE.SAYHELLO.ReplyTo = 'http://www.w3.org/2005/08/addressing/anonymous'\n" +
"AND ADDRESSINGSERVICE.SAYHELLO.Action = 'http://www.w3.org/2005/08/addressing/ServiceIface/sayHello'";
ResultSet rs = stmt.executeQuery(sql);
assertTrue(rs.next());
assertEquals("Hello World!", rs.getString(1));
conn.close();
}
}
Binary file not shown.
37 changes: 37 additions & 0 deletions test-integration/common/src/test/resources/soapsvc-vdb.xml
@@ -0,0 +1,37 @@
<vdb name="WSMSG" version="1">
<model name="test">
<source name="src" connection-jndi-name="java:/web-ds" translator-name="ws1"/>
</model>

<model name="AddressingService" type="VIRTUAL">
<metadata type = "DDL"><![CDATA[
CREATE VIRTUAL PROCEDURE sayHello(IN sayHello string NOT NULL, IN MessageID string NOT NULL, IN "To" string NOT NULL, IN ReplyTo string NOT NULL, IN Action string NOT NULL) RETURNS TABLE (sayHelloResponse string)
AS
BEGIN
SELECT t.* FROM TABLE(EXEC AddressingService.sayHello_request(AddressingService.sayHello.sayHello, AddressingService.sayHello.MessageID, AddressingService.sayHello."To", AddressingService.sayHello.ReplyTo, AddressingService.sayHello.Action)) AS request, TABLE(EXEC test.invoke(binding => 'SOAP11', action => '', request => request.xml_out, endpoint => 'http://localhost:8080/jboss-jaxws-addressing/AddressingService', stream => TRUE)) AS response, TABLE(EXEC AddressingService.sayHello_response(response.result)) AS t;
END;
CREATE VIRTUAL PROCEDURE sayHello_request(IN sayHello string NOT NULL, IN MessageID string NOT NULL, IN "To" string NOT NULL, IN ReplyTo string NOT NULL, IN Action string NOT NULL) RETURNS TABLE (xml_out xml)
AS
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", AddressingService.sayHello_request.MessageID), XMLELEMENT(NAME "wsa:To", AddressingService.sayHello_request."To"), XMLELEMENT(NAME "wsa:ReplyTo", AddressingService.sayHello_request.ReplyTo), XMLELEMENT(NAME "wsa:Action", AddressingService.sayHello_request.Action)), XMLELEMENT(NAME "soap:Body", XMLELEMENT(NAME "tns:sayHello", AddressingService.sayHello_request.sayHello))) AS xml_out;
END;
CREATE VIRTUAL PROCEDURE sayHello_response(IN xml_in xml NOT NULL) RETURNS TABLE (sayHelloResponse string)
AS
BEGIN
EXECUTE logMsg(context=>'org.teiid', level=>'ERROR', msg=>XMLSERIALIZE(sayHello_response.xml_in AS string));
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/soap:Body' PASSING AddressingService.sayHello_response.xml_in
COLUMNS sayHelloResponse string PATH 'tns:sayHelloResponse/return') AS t;
END;
]]>
</metadata>
</model>

<translator name="ws1" type="ws">
<property name="DefaultBinding" value="SOAP12"/>
<property name="DefaultServiceMode" value="MESSAGE"/>
</translator>
</vdb>

0 comments on commit 3f71a69

Please sign in to comment.