OK, here's what seems to be working for me... It's a horrible hack, but it
works...
First, take your WSDL file and turn it into RPC/literal (for me it was as easy as
replacing the word "encoded" with "literal").
Next, setup your JBossWS stuff as though you will be receiving RPC/literal documents (from
its standpoint, you will).
Now for the tricky part... You will have already setup a servlet (@WebService), which you
now need to add an XSLT filter to...
All I had to do to make my SOAP messages understandable to JBossWS was flatten the
"multiRef" nodes.
Original SOAP message:
| <myWebServiceMethod>
| <myArgumentObject href="#id0"/>
| </myWebServiceMethod>
| <multiRef id="id0" ...>
| <actualGutsOfArgument/>
| <referencedGutNum2 href="#id2"/>
| </multiRef>
| <multiRef id="id2" ...>
| <moreActualGuts/>
| </multiRef>
|
Flattened SOAP message:
| <myWebServiceMethod>
| <myArgumentObject id="id0" ...>
| <actualGutsOfArgument/>
| <referencedGutNum2 id="id2" ...>
| <moreActualGuts/>
| </referencedGutNum2>
| </myArgumentObject>
| </myWebServiceMethod>
|
Note: The only attribute I removed was "href", all of the attributes to the
multiRef node became attributes to the node that referenced it (this includes xsi:type
info which I believe gets ignored anyway since it is already specified in the XSD file
that my WSDL references).
The filter will look something like this:
| public class MultiRefFlattener
| implements Filter
| {
| private Transformer m_transformer = null;
|
| public void init ( FilterConfig filterConfig )
| throws ServletException
| {
| final String stylePath = filterConfig.getServletContext().getRealPath(
"WEB-INF/multi-ref-flattener.xslt" );
| final Source styleSource = new StreamSource( stylePath );
| final TransformerFactory transformerFactory = TransformerFactory.newInstance();
| try
| {
| m_transformer = transformerFactory.newTransformer( styleSource );
| }
| catch( TransformerConfigurationException e )
| {
| throw new ServletException( "Error creating XSLT transformer: ", e
);
| }
| }
|
| public void doFilter(
| final ServletRequest request,
| final ServletResponse response,
| final FilterChain chain )
| throws IOException, ServletException
| {
| final String requestText;
| try
| {
| final CharArrayWriter caw = new CharArrayWriter();
| final StreamResult result = new StreamResult(caw);
| m_transformer.transform(new StreamSource(request.getInputStream()), result);
| requestText = caw.toString();
| }
| catch( TransformerException e )
| {
| throw new ServletException( "Error filtering data" );
| }
|
| final ServletInputStream requestStream = new ServletInputStream()
| {
| private int m_column = 0;
| public int read ()
| throws IOException
| {
| if( m_column >= requestText.length() )
| return -1;
| final int character = requestText.charAt( m_column );
| ++m_column;
| return character;
| }
| };
|
| final HttpServletRequest httpServletRequest = (HttpServletRequest)request;
| final HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(
httpServletRequest )
| {
| @Override
| public int getContentLength ()
| {
| return requestText.length();
| }
|
| @Override
| public ServletInputStream getInputStream ()
| throws IOException
| {
| return requestStream;
| }
| };
| chain.doFilter( wrapper, response );
| }
|
| public void destroy ()
| {
| m_transformer = null;
| }
| }
|
If anybody has a better way of faking an HttpServletRequest, please let me know.
And here is my flattening XSLT file:
| <xsl:stylesheet version="1.0"
|
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
|
| <xsl:template match="/">
| <xsl:call-template name="CopyNode"/>
| </xsl:template>
|
| <xsl:template name="CopyNodeRef">
| <xsl:param name="elementName"/>
| <xsl:param name="hrefId"/>
| <xsl:copy>
| <xsl:element name="$elementName">
| <xsl:for-each select="//multiRef[@id = $hrefId]/@*">
| <xsl:copy>
| <xsl:apply-templates mode="keeping"/>
| </xsl:copy>
| </xsl:for-each>
| <xsl:for-each select="//multiRef[@id =
$hrefId]/node()[not(@href)]">
| <xsl:call-template name="CopyNode"/>
| </xsl:for-each>
| <xsl:for-each select="//multiRef[@id =
$hrefId]/node()[@href]">
| <xsl:call-template name="CopyNodeRef">
| <xsl:with-param name="elementName"
select="name()"/>
| <xsl:with-param name="hrefId"
select="substring(@href, 2)"/>
| </xsl:call-template>
| </xsl:for-each>
| </xsl:element>
| </xsl:copy>
| </xsl:template>
|
| <xsl:template name="CopyNode">
| <xsl:copy>
| <xsl:call-template name="CopyAttributes"/>
| <xsl:for-each select="node()[not(@href|@id)]">
| <xsl:call-template name="CopyNode"/>
| </xsl:for-each>
| <xsl:for-each select="node()[@href]">
| <xsl:call-template name="CopyNodeRef">
| <xsl:with-param name="elementName"
select="name()"/>
| <xsl:with-param name="hrefId"
select="substring(@href, 2)"/>
| </xsl:call-template>
| </xsl:for-each>
| </xsl:copy>
| </xsl:template>
|
| <xsl:template name="CopyAttributes">
| <xsl:for-each select="@*">
| <xsl:copy>
| <xsl:apply-templates mode="keeping"/>
| </xsl:copy>
| </xsl:for-each>
| </xsl:template>
|
| </xsl:stylesheet>
|
If anybody has a better idea for a flattener, please let me know.
I hope this helps.
-Shadow
View the original post :
http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4269863#...
Reply to the post :
http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&a...