[jboss-user] [JBoss Web Services Users] - Re: How to recieve RPC/encoded SOAP messages in JBoss5?

shadowcreeper do-not-reply at jboss.com
Wed Dec 9 14:47:46 EST 2009


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#4269863

Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4269863



More information about the jboss-user mailing list