Pergunta

I inherited a web service that used to work fine until we had to upgrade the runtime environment (from JBOSS/JRE6 to Tomcat7/JRE7). There was no code change except for the pom.xml!

In fact it still works fine, except that the many existing clients can no longer handle the response because of an extra namespace attribute now present in one of the elements (of the response).

That is, previously (before the migration) that element (in the SOAP response) used to be:

<OurResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
             xsi:noNamespaceSchemaLocation="OurResponse.xsdXMLSchema-instance" 
             ourresponseVersion="M1m2v03" xmlns="">

And now it is:

<v01:OurResponse acknowledgementVersion="M1m2v03" 
     xmlns:v01="http://webservice.ourdomain.com/projone/modtwo/M1m2v03">

Since there was no code change involved, I am baffled by this (minor but critical) change in the SOAP response.

In particular, I am trying to understand:

  1. Which part of the build system changes this namespace attribute?
  2. How do I restore it back to previous behavior?
  3. Why would the clients break on such a minor change? (i.e. the content of the response is identical!)

The only relevant changes I have been able to spot in the pom.xml are:

  1. Adding the following dependencies:

    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk16</artifactId>
        <version>1.46</version>
    </dependency>
    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache</artifactId>
        <version>2.7.4</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>3.0.7.RELEASE</version>
        <exclusions>
            <exclusion>
                <groupId>net.sf.ehcache</groupId>
                <artifactId>ehcache</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
  2. Updating the cxf-rt-frontend-jaxws dependency from version 2.2.7 to 2.7.7.

  3. Updating the cxf-rt-transports-http dependency from version 2.2.7 to 2.7.7.

  4. Updating the cxf-rt-ws-security dependency from version 2.2.7 to 2.7.7.

  5. Adding the following dependencies:

    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-core</artifactId>
        <version>2.7.7</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-databinding-aegis</artifactId>
        <version>2.7.7</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-management</artifactId>
        <version>2.7.7</version>
    </dependency>
    

Again, I am assuming there is some internal change in one of the frameworks involved (CXF? Spring?) that handles this internally. If this assumption is correct, then:

  1. Which part of the build system changes this namespace attribute?
  2. How do I restore it back to previous behavior?
  3. Why would the clients break on such a minor change? (i.e. the content of the response is identical!)

Update 1: The culprit turned out to be the org.apache.cxf packages version change from 2.2.7 to 2.7.7.

Looks like newer is not always better... unless there is a way to programmatically to force the legacy behavior of stripping out the namespace prefixes?

Update 2: Using CXF 2.2.7 on Tomcat7/JRE7 had the side-effect of killing the Tomcat server after sending a single SOAP message (seems to be related to SSL).

The fact that a venerable server like Tomcat can die due to a single rogue .war package is pretty disturbing but since I cannot fix Tomcat and I have not found a programmatic way to workaround the implicit namespace prefix issue, I tried various stable CXF releases that would exhibit the legacy behavior without killing Tomcat.

I tried versions 2.7.1 and 2.6.10 but eventually only 2.5.9 worked.

I hope this helps someone who stumbles on a similar problem.

Foi útil?

Solução

Conforming XML implementation are not permitted to die due to changes in the use of xmlns attributes. Expressing the same data model with a prefix or without, it's the same thing. If your client failed, you need to fix the client. If you have clients that are hypersensitive to the use of namespace prefixes instead of to the real data model, CXF is not necessarily a good choice.

Most likely CXF upgraded to a more recent version of JAX-B, and it changed its mind about the namespace prefixes.

To elaborate this: Apache CXF was designed to focus on standard-conforming web services. Apache Axis has traditionally filled the space for not-so-standard-conforming web services, just fine. So no, the CXF development community has never worried about 'prefix stability'. If the XML is formally correct, CXF tests are happy.

For this, and many other reasons, CXF delegates XML generation for JAX-B web services to the official JAX-B reference implementation. New versions of CXF pick up new versions of JAX-B. JAX-B, from time to time, makes changes that have the effect of rearranging the namespace prefixes.

The XML generation in CXF is pluggable, so if you want to use an older JAX-B, or roll your own, you can. You can provide a 'Provider' and do the whole job yourself if you like.

There is an option in CXF to pass an object into JAX-B that decides what prefix to use for what namespace, but I don't think that it can be used to force a particular namespace to be defaulted. You might be able to get what you want with a Provider and a carefully configured call to the JAX-B API.

The CXF User mailing list archive has hundreds of messages to and from people who are swimming upstream with namespace prefixes.

(As for tomcat dying, well, that's another question.)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top