2 Replies Latest reply on Jul 21, 2017 11:26 AM by ulablue

    Using Metro in JBoss AS 7.2.0 Final

    tmfkell

      Dear Community,

       

      recently I've been doing some research on how to migrate an application from JBoss AS 5.1.0 to JBoss AS 7.2.0 Final.

       

      The main features of the application are:

      - it's a spring application (+struts+tiles)

      - the services are implemented as ejbs

      - it operates as client for different web services

      - it doesn't provide own web services

      - it uses Metro stack (2.2.1-1)

       

      Of course, the goal is and was to keep all the functionality without massive changes - neither on application nor on application server level.

       

      Suprisingly the number of critical, deployment-preventing issues was marginal:

      - mapping existing configuration to new model

      - integrating with security/ldap

      - add external application configuration file to classpath via JBoss Module

      - jndi-url-schema

      - change some xml-files to be conform to spec (tld-files).

       

      The main problem was to establish the ws-communication at runtime. Apache CXF didn't work out of the box. Some time ago, we integrated Metro in JBoss 5.1.0 due to the policy requirements of a ws provider which defined a bunch of non-optional policies such as WS-Policy 1.5, WS-SecurityPolicy 1.2, WS-RM Policy (RMP) 1.2:

       

      <wsp:Policy wsu:Id="ServicePolicy">

      <wsp:ExactlyOne>

      <wsp:All>

      <wsam:Addressing wsp:Optional="false" />

      <wsrm:RMAssertion>

      <wsp:Policy>

      <wsrm:SequenceTransportSecurity />

      </wsp:Policy>

      </wsrm:RMAssertion>

      <sp:TransportBinding>

      <wsp:Policy>

      <sp:TransportToken>

      <wsp:Policy>

      <sp:HttpsToken RequireClientCertificate="false" />

      </wsp:Policy>

      </sp:TransportToken>

      <sp:Layout>

      <wsp:Policy>

      <sp:Lax />

      </wsp:Policy>

      </sp:Layout>

      <sp:IncludeTimestamp />

      <sp:AlgorithmSuite>

      <wsp:Policy>

      <sp:Basic128 />

      </wsp:Policy>

      </sp:AlgorithmSuite>

      </wsp:Policy>

      </sp:TransportBinding>

      <sp:Wss10 />

      <sp:Trust13 /> <!-- causes Exception in Apache CXF -->

      <sp:EndorsingSupportingTokens>

      <wsp:Policy>

      <sp:SecureConversationToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">

      <wsp:Policy>

      <sp:BootstrapPolicy>

      <wsp:Policy>

      <sp:TransportBinding>

      <wsp:Policy>

      <sp:TransportToken>

      <wsp:Policy>

      <sp:HttpsToken RequireClientCertificate="false" />

      </wsp:Policy>

      </sp:TransportToken>

      <sp:Layout>

      <wsp:Policy>

      <sp:Strict />

      </wsp:Policy>

      </sp:Layout>

      <sp:IncludeTimestamp />

      <sp:AlgorithmSuite>

      <wsp:Policy>

      <sp:Basic128 />

      </wsp:Policy>

      </sp:AlgorithmSuite>

      </wsp:Policy>

      </sp:TransportBinding>

      <sp:EncryptedParts>

      <sp:Body />

      </sp:EncryptedParts>

      <sp:SignedParts>

      <sp:Body />

      <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />

      <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" />

      <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" />

      <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" />

      <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" />

      <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" />

      <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" />

      <sp:Header Name="AckRequested" Namespace="http://docs.oasis-open.org/ws-rx/wsrm/200702" />

      <sp:Header Name="SequenceAcknowledgement" Namespace="http://docs.oasis-open.org/ws-rx/wsrm/200702" />

      <sp:Header Name="Sequence" Namespace="http://docs.oasis-open.org/ws-rx/wsrm/200702" />

      <sp:Header Name="CreateSequence" Namespace="http://docs.oasis-open.org/ws-rx/wsrm/200702" />

      </sp:SignedParts>

      <sp:SignedEncryptedSupportingTokens>

      <wsp:Policy>

      <sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">

      <wsp:Policy>

      <sp:WssUsernameToken10 />

      </wsp:Policy>

      </sp:UsernameToken>

      </wsp:Policy>

      </sp:SignedEncryptedSupportingTokens>

      </wsp:Policy>

      <sp:Wss11>

      <wsp:Policy>

      <sp:MustSupportRefIssuerSerial />

      <sp:MustSupportRefThumbprint />

      <sp:MustSupportRefEncryptedKey />

      </wsp:Policy>

      </sp:Wss11>

      <sp:Trust13>

      <wsp:Policy>

      <sp:MustSupportIssuedTokens />

      <sp:RequireClientEntropy />

      <sp:RequireServerEntropy />

      </wsp:Policy>

      </sp:Trust13>

      </sp:BootstrapPolicy>

      </wsp:Policy>

      </sp:SecureConversationToken>

      </wsp:Policy>

      </sp:EndorsingSupportingTokens>

      </wsp:All>

      </wsp:ExactlyOne>

      </wsp:Policy>

       

       

      When integrating Metro, it seemed to be the only framework that supports all these policies. We finally got ws-access and -communication working by simply replacing the jboss ws-native jars by the Metro jars and setting up some properties for username, password (see http://www.oio.de/public/xml/usernametoken-tutorial-webservice-security-artikel.htm) and timeout. No need to handle with policy feature configuration, probably since the WS is also implemented with Metro.

       

      Now, while still doing research on migration, we had the choice: either A) map the (currently minimal) configuration-code from Metro to Apache CXF or B) use Metro in JBoss AS 7.2.

       

      I read some documentations about Apache CXF (2.6.6 ships with JBoss 7.2.0 Final) and its features and configurations. I also tried some Apache CXF examples with little success. If I get it right the support for WS-RMP1.2 is not yet implemented in 2.6.6.

      In addition, the WSDL given by the ws provider (according to comments generated by Metro) was not parsable - it leads to the following exception:


      java.lang.IllegalArgumentException: Trust13 assertion doesn't contain any Policy

         at org.apache.cxf.ws.security.policy.builders.Trust13Builder.build(Trust13Builder.java:40)

         at org.apache.cxf.ws.security.policy.builders.Trust13Builder.build(Trust13Builder.java:34)

         at org.apache.neethi.AssertionBuilderFactoryImpl.invokeBuilder(AssertionBuilderFactoryImpl.java:138)

         at org.apache.neethi.AssertionBuilderFactoryImpl.build(AssertionBuilderFactoryImpl.java:117)

         ...

       

      Finally we decided to try B) Metro on JBoss AS 7.2.

       

      There are only a few posts dealing with Metro on JBoss. In JBoss AS 7 Apache CXF is everybodys darling and so there's few support for Metro, the outcast adoptive child.

      I got inspired by the posts, that there might be a way, to get it working.

      - https://community.jboss.org/thread/173486

      - https://community.jboss.org/thread/204752

      - https://community.jboss.org/message/732708

      Because these posts are quite old I'm trying to start a new one.

       

      --------------------------------------------------

       

      Finally, I got communication working with Metro in JBoss AS 7 without code changes by using the following configuration in JBoss AS 7.2.0 Final:

       

      1. provided a Metro-module (Metro 2.2.1-1) with following structure:

       

      -module.xml

      -webservices-api.jar

      -webservices-extra-api.jar

      -webservices-extra.jar

      -webservices-rt.jar

      -webservices-tools.jar

      -service-loader-resources

      -services

      -javax.xml.ws.spi.Provider

       

      I my case I chose the module name 'com.sun.xml.ws'.

      The file javax.xml.ws.spi.Provider contains the class-name of the Metro Provider Implementation which is 'com.sun.xml.ws.spi.ProviderImpl'.

       

      The module.xml has the following content:declaring dependencies

       

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

      <module xmlns="urn:jboss:module:1.1" name="com.sun.xml.ws">

      <resources>

      <resource-root path="webservices-rt.jar"/>

      <resource-root path="webservices-api.jar"/>

      <resource-root path="webservices-extra.jar"/>

      <resource-root path="webservices-extra-api.jar"/>

      <resource-root path="webservices-tools.jar"/>

      <resource-root path="service-loader-resources"/>

      </resources>

      <dependencies>

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

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

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

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

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

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

      <module name="javax.security.auth.message.api"/>

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

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

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

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

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

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

      <module name="nu.xom"/>

      <module name="org.apache.xerces"/>

      <module name="org.apache.xml-resolver"/>

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

      <system>

      <paths>

      <path name="com/sun/org/apache/xerces/internal/dom"/>

      <path name="com/sun/org/apache/xerces/internal/jaxp"/>

      <path name="javax/xml/transform"/>

      <path name="javax/xml/parsers"/>

      <path name="javax/xml/transform/dom"/>

      <path name="javax/xml/transform/sax"/>

      <path name="javax/xml/transform/stax"/>

      <path name="javax/xml/transform/stream"/>

      <path name="javax/xml/namespace"/>

      <path name="org/xml/sax"/>

      <path name="org/xml/sax/helpers"/>

      <path name="org/xml/sax/ext"/>

      <path name="com/sun/xml/internal"/>

      <path name="com/sun/xml/internal/ws"/>

      <path name="com/sun/org/apache/xml/internal/resolver"/>

      <path name="com/sun/org/apache/xml/internal/resolver/tools"/>

      <path name="javax/xml/datatype"/>

      <path name="javax/management"/>

      <path name="javax/management/openmbean"/>

      <path name="javax/management/modelmbean"/>

      <path name="org/w3c/dom"/>

      <path name="javax/xml/validation"/>

      <path name="META-INF/services"/>

      </paths>

      <exports>

      <include-set>

      <path name="META-INF/services"/>

      <!-- due to applications dependency to class Closable (close sequence for WS-RM1.1, see https://community.jboss.org/wiki/JBossWS-MetroWS-ReliableMessagingTutorial) -->

      <path name="com/sun/xml/internal/ws"/>

      </include-set>

      </exports>

      </system>

      </dependencies>

      </module>

       

       

      2. changed the module.xml file of the modules 'javax.xml.soap.api' and 'javax.xml.ws.api' to disable "class loading hacks". Therefore we removed the dependency to the 'org.jboss.modules'-module.

       

      -javax.xml.soap.api:

       

      <module xmlns="urn:jboss:module:1.1" name="javax.xml.soap.api">

      <dependencies>

      <module name="javax.activation.api" export="true"/>

      <module name="javax.api"/>

      <!--<module name="org.jboss.modules"/>-->

      </dependencies>

      <resources>

      <resource-root path="jboss-saaj-api_1.3_spec-1.0.2.Final.jar"/>

      </resources>

      </module>

       

       

      -javax.xml.ws.api:

       

      <module xmlns="urn:jboss:module:1.1" name="javax.xml.ws.api">

      <dependencies>

      <module name="javax.xml.bind.api" export="true"/>

      <module name="javax.xml.soap.api" export="true"/>

      <module name="javax.api"/>

      <!--<module name="org.jboss.modules"/>-->

      </dependencies>

      <resources>

      <resource-root path="jboss-jaxws-api_2.2_spec-2.0.1.Final.jar"/>

      </resources>

      </module>


       

      3. added an depedency to the Metro-module, so the Metro Provider gets found at runtime. We did this by declaring it to a global module. Therefore we added following lines to the standalone.xml:

       

      <subsystem xmlns="urn:jboss:domain:ee:1.1">

      <global-modules>

      <module name="com.sun.xml.ws" slot="main"/>

      </global-modules>

      </subsystem>

       

      Alternatively setting the dependency on application level is also possible by providing a jboss-deployment-structure.xml in META-INF-directory of the ear:

       

      <jboss-deployment-structure>

      <ear-subdeployments-isolated>false</ear-subdeployments-isolated>

      <deployment>

      <dependencies>

      <module name="com.sun.xml.ws" export="true" services="export"/>

      </dependencies>

      </deployment>

      </jboss-deployment-structure>

       

      --------------------------------------------------

       

       

      As I said, this solution fits for our application and we're now ready to migrate. Let me again stress that our application only acts as ws client - with no own web services provided. I'm quite certain providing own web wervices in production would force us to do a bit more changes on class loading.

       

      Nevertheless I was able to deploy a dummy implementation of the web service (jaxws 2.2, without any policies) for test purposes. It get's regularily (and successfully) deployed with Apache CXF. Switching to Metro is possible by removing the webservices extension/subsystem from standalone.xml or manually excluding the webservices-subsystem in the jboss-deployment-structure.xml of the war-file:

       

      <exclude-subsystems>

      <subsystem name="webservices"/>

      </exclude-subsystems>

       

      Since it's not the common way to solve the problem, would you like to give me some advice what I'm missing?

      Will these changes cause some class loading issues that I'm not aware of?

      Any pointers or suggestions? Is there maybe a way to fulfill our given policy requirements with Apache CXF (in JBoss 7.2.0)?

       

      Thanks

        • 1. Re: Using Metro in JBoss AS 7.2.0 Final
          druker

          Thank you for the great post.

           

          I have a weird request: do you remember how you deployed an app based on Metro (2.2.1) to JBoss AS 5.1.0 ?

          • 2. Re: Using Metro in JBoss AS 7.2.0 Final
            ulablue

            Thanks.

             

            In wildfly 10.x  after adapting above config,  below exception.

             

            It looks like the still the org.jboss module __redirected.__XMLInputFactory is being used.

            any ideas ?

             

            Caused by: com.sun.xml.ws.transport.http.servlet.WSServletException: WSSERVLET11: failed to parse runtime descriptor: java.lang.ExceptionInInitializerError

            at com.sun.xml.ws.transport.http.servlet.WSServletContextListener.parseAdaptersAndCreateDelegate(WSServletContextListener.java:137)

            at com.sun.xml.ws.transport.http.servlet.WSServletContainerInitializer.onStartup(WSServletContainerInitializer.java:61)

            ... 9 more

            Caused by: java.lang.ExceptionInInitializerError

            at com.sun.xml.ws.transport.http.DeploymentDescriptorParser.parse(DeploymentDescriptorParser.java:144)

            at com.sun.xml.ws.transport.http.servlet.WSServletContextListener.parseAdaptersAndCreateDelegate(WSServletContextListener.java:127)

            ... 10 more

            Caused by: java.lang.ClassCastException: __redirected.__XMLInputFactory cannot be cast to javax.xml.stream.XMLInputFactory

            at javax.xml.stream.XMLInputFactory.newInstance(XMLInputFactory.java:136)

            at com.sun.xml.ws.api.streaming.XMLStreamReaderFactory.getXMLInputFactory(XMLStreamReaderFactory.java:109)

            at com.sun.xml.ws.api.streaming.XMLStreamReaderFactory.<clinit>(XMLStreamReaderFactory.java:78)

            ... 12 more