martes, 30 de agosto de 2011

"compiler was unable to honor this globalBindings customization" using CXF's DynamicClientFactory

I'm using CXF 2.4.2 and DynamicClientFactory. To simplify the runtime classes manipulation I wanted to make sure the generated Java clases didn´t contain JAXBElement attributes; so I created the famous generateElementProperty globalBindings JAXB binding file.

I used the createClient method that receives the binding list to feed DynamicClientFactory with my file, but I received the following JAXB error: compiler was unable to honor this globalBindings customization. It is attached to a wrong place, or its inconsistent with other bindings.

I found this error may occur if you use more than one binding file with globalBindings declarations. I dug into the DynamicClientFactory code and found that by default, CXF use one binding file with globalBindings declarations: /org/apache/cxf/endpoint/dynamic/simple-binding.xjb in the addSchemas method. Thus, besides my binding file, there was another file internally used by CXF. Luckily, the binding file included by CXF have the generateElementProperty declaration that I was trying to configure with my binding file.

I checked the runtime generated classes and indeed (modifying the DynamicClientFactory class to not delete the source files) they did'n include the JAXBElement attributes when they would normally do.

It was no necesary to include my extra binding file.

This is a fragment of the stack trace:

Caused by: java.lang.reflect.UndeclaredThrowableException
    at $Proxy25.error(Unknown Source)
    at com.sun.tools.xjc.api.impl.s2j.SchemaCompilerImpl.error(SchemaCompilerImpl.java:286)
    at com.sun.tools.xjc.util.ErrorReceiverFilter.error(ErrorReceiverFilter.java:77)
    at com.sun.tools.xjc.util.ErrorReceiverFilter.error(ErrorReceiverFilter.java:77)
    at com.sun.tools.xjc.ErrorReceiver.error(ErrorReceiver.java:82)
    at com.sun.tools.xjc.reader.xmlschema.ErrorReporter.error(ErrorReporter.java:79)
    at com.sun.tools.xjc.reader.xmlschema.UnusedCustomizationChecker.check(UnusedCustomizationChecker.java:144)
    at com.sun.tools.xjc.reader.xmlschema.UnusedCustomizationChecker.check(UnusedCustomizationChecker.java:122)
    at com.sun.tools.xjc.reader.xmlschema.UnusedCustomizationChecker.schema(UnusedCustomizationChecker.java:199)
    at com.sun.tools.xjc.reader.xmlschema.UnusedCustomizationChecker.run(UnusedCustomizationChecker.java:95)
    at com.sun.tools.xjc.reader.xmlschema.BGMBuilder._build(BGMBuilder.java:187)
    at com.sun.tools.xjc.reader.xmlschema.BGMBuilder.build(BGMBuilder.java:116)
    at com.sun.tools.xjc.ModelLoader.annotateXMLSchema(ModelLoader.java:415)
    at com.sun.tools.xjc.api.impl.s2j.SchemaCompilerImpl.bind(SchemaCompilerImpl.java:245)
    ... 32 more
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:592)
    at org.apache.cxf.common.util.ReflectionInvokationHandler.invoke(ReflectionInvokationHandler.java:52)
    ... 46 more
Caused by: java.lang.RuntimeException: 
    Error compiling schema from WSDL at {http://xxx?wsdl}: compiler was unable to honor this globalBindings customization. It is attached to a wrong place, or its inconsistent with other bindings.
    at org.apache.cxf.endpoint.dynamic.DynamicClientFactory$InnerErrorListener.error(DynamicClientFactory.java:582)
    ... 51 more
Caused by: com.sun.istack.SAXParseException2: compiler was unable to honor this globalBindings customization. It is attached to a wrong place, or its inconsistent with other bindings.
    ... 42 more


Update (2013/08/14): I tried the same codebase with CXF 2.6.1, but started having issues with JAXBElement attributes appearing in the generated Java classes. I dug again into the DynamicClientFactory code and found in SVN revision 1232564 ([CXF-4037] Allow dynamic client to use already parsed and processed schemas like the tooling does), the code section that included the default binding file (simple-binding.xjb) was removed. It haven't been included in posterior commits (last trunk revision now for DynamicClientFactory is 1502354).

This is one version of the DynamicClientFactory.java's removed code section:

if (simpleBindingEnabled) {
String id = "/org/apache/cxf/endpoint/dynamic/simple-binding.xjb";
LOG.fine("Loading the JAXB 2.1 simple binding for client.");
try {
Document doc = StaxUtils.read(getClass().getResourceAsStream(id));
compiler.parseSchema(id, doc.getDocumentElement());
} catch (XMLStreamException e) {
LOG.log(Level.WARNING, "Could not parse simple-binding.xsd", e);
}
}

Due to the fact my code is not expecting JAXBElement attributes in the generated classes, I'm including the binding (again) by myself.

My binding:

<bindings version="2.1"
  xmlns="http://java.sun.com/xml/ns/jaxb"
  xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">
  <bindings>
    <globalBindings>
      <xjc:generateElementProperty>false</xjc:generateElementProperty>
    </globalBindings>
  </bindings>
</bindings>

The CXF's equivalent binding:

<jaxb:bindings
  xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
  xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc">
 
  <jaxb:globalBindings generateElementProperty="false">
    <xjc:simple />
  </jaxb:globalBindings>
</jaxb:bindings>

No hay comentarios: