Uploaded image for project: 'CXF'
  1. CXF
  2. CXF-3946

<property name="namespacePrefixes" ref="namespaceMap" /> causes exception due to immutable Map being used in JAXBElementProvider

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Trivial
    • Resolution: Fixed
    • 2.5
    • 2.4.5, 2.5.1
    • JAX-RS, JAXB Databinding
    • None
    • Novice

    Description

      I was trying to set a specific namespace prefix for a qualified REST xml.

      I configured beans.xml and included package-info.java as below:

      @javax.xml.bind.annotation.XmlSchema( namespace=GoldenKey.NS,
      elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
      attributeFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
      xmlns=

      {@javax.xml.bind.annotation.XmlNs(prefix = GoldenKey.NS_QUALIFIER , namespaceURI=GoldenKey.NS)}

      )

      package com.upmc.tdc.xml;

      beans.xml snippets:

      <jaxrs:server id="goldenKey_rest" address="/rest">
      <jaxrs:serviceBeans>
      <ref bean="goldenKey_bean" />
      </jaxrs:serviceBeans>
      <jaxrs:extensionMappings>
      <entry key="json" value="application/json" />
      <entry key="xml" value="application/xml" />
      </jaxrs:extensionMappings>
      <jaxrs:providers>
      <ref bean="dateProvider" />
      <ref bean="exceptionMapper" />
      <ref bean="jaxbProvider" />
      </jaxrs:providers>
      </jaxrs:server>

      <jaxws:endpoint serviceName="GoldenKey" endpointName="GoldenKeyPort" id="goldenKey_soap" implementor="#goldenKey_bean" address="/soap">
      <jaxws:binding>
      <soap:soapBinding version="1.2" />
      </jaxws:binding>
      <jaxws:features>
      <bean class="org.apache.cxf.feature.LoggingFeature">
      <property name="prettyLogging" value="true" />
      </bean>
      </jaxws:features>
      </jaxws:endpoint>

      <bean id="goldenKey_bean" class="com.upmc.tdc.server.GoldenKeyImpl"/>
      <bean id="dateProvider" class="com.upmc.tdc.server.parameterhandler.DateParameterHandler"/>
      <bean id="exceptionMapper" class="com.upmc.tdc.exception.ExceptionMapper"/>

      <bean id="jaxbProvider" class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
      <property name="marshallerProperties" ref="propertiesMap" />
      <property name="namespacePrefixes" ref="namespaceMap" />
      <property name="enableBuffering" value="true" />
      </bean>

      <util:map id="propertiesMap">
      <entry key="jaxb.formatted.output">
      <value type="java.lang.Boolean">true</value>
      <!-- prints indented XML for REST, useful for testing, can be disabled for production -->
      </entry>
      </util:map>

      <util:map id="namespaceMap">
      <entry key="http://server.tdc.upmc.com/" value="GoldenKey"/>
      </util:map>

      This setup throws the following exception:

      java.lang.UnsupportedOperationException
      at java.util.AbstractMap.put(AbstractMap.java:203)
      at java.util.AbstractMap.putAll(AbstractMap.java:273)
      at org.apache.cxf.jaxrs.provider.JAXBElementProvider.marshalCollectionMember(JAXBElementProvider.java:327)
      at org.apache.cxf.jaxrs.provider.JAXBElementProvider.marshalCollection(JAXBElementProvider.java:293)
      at org.apache.cxf.jaxrs.provider.JAXBElementProvider.writeTo(JAXBElementProvider.java:232)
      at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.serializeMessage(JAXRSOutInterceptor.java:257)
      at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.processResponse(JAXRSOutInterceptor.java:144)
      at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.handleMessage(JAXRSOutInterceptor.java:83)
      at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
      <clipped>

      Lines 325-330 of JAXBElementProvider.java contain the following code:
      if (ns.length() > 0)

      { Map<String, String> map = Collections.singletonMap(ns, "ns1"); map.putAll(nsPrefixes); setNamespaceMapper(ms, map); }

      marshal(obj, cls, genericType, enc, os, mt, ms);

      The call Collections.singletonMap(...) is below:

      /**

      • Returns an immutable map, mapping only the specified key to the
      • specified value. The returned map is serializable.
        *
      • @param key the sole key to be stored in the returned map.
      • @param value the value to which the returned map maps <tt>key</tt>.
      • @return an immutable map containing only the specified key-value
      • mapping.
      • @since 1.3
        */
        public static <K,V> Map<K,V> singletonMap(K key, V value) { return new SingletonMap<>(key, value); }

      So it seems that
      map.putAll(nsPrefixes);

      should fail as it is failing when called because the map is immutable.

      In case there are other prefixes to add it seems that the map should be of another type....

      Attachments

        Activity

          People

            sergey_beryozkin Sergey Beryozkin
            jrfeitosamm Miguel Martins Feitosa Jr.
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: