eclipse-ee4j / metro-jax-ws

metro-jax-ws
https://eclipse-ee4j.github.io/metro-jax-ws/
BSD 3-Clause "New" or "Revised" License
68 stars 40 forks source link

WsGen generating wrong XSDs #647

Closed jbescos closed 1 year ago

jbescos commented 1 year ago

Reproducer:

git clone https://github.com/jbescos/Questions.git
cd Questions/wsgenXsdIssue
# Modify the JAVA_HOME in the script
./runExample.sh

Then check wsGenGenerated/ProviderMaintenanceServiceStronglyTyped_schema1.xsd generated by WsGen. Check also what is supposed to be the correct XSD generated by SchemaGen in schemaGenerated/schema1.xsd.

Given:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "")
@XmlRootElement(name = "generalCorrespondenceAddress")
public class GeneralCorrespondenceAddress implements Serializable {

    private final static long serialVersionUID = 1L;
    protected AddressInformation addressInformation;
...

The issue is that the generated XSD under wsGenGenerated/ProviderMaintenanceServiceStronglyTyped_schema1.xsd looks like:

  <xs:element name="addressInformation">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="addressPhoneList" minOccurs="0">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="telephone" nillable="true" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
...
  <xs:element name="generalCorrespondenceAddress">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="addressInformation" minOccurs="0"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

Note that addressInformation is not expanded under generalCorrespondenceAddress. I think the correct way is: <xs:element ref="tns:addressInformation" minOccurs="0"/>

This makes that later, when you use the WSDL with WsImport, it generates the next wsImportGenerated/com/test/GeneralCorrespondenceAddress.java:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "addressInformation"
})
@XmlRootElement(name = "generalCorrespondenceAddress")
public class GeneralCorrespondenceAddress {

    protected Object addressInformation;
...

The issue is that we can see Object addressInformation , but it should be AddressInformation addressInformation

jbescos commented 1 year ago

If I try with JDK8 (I also have to change jakarta by javax) and I remove the classpath (so I only use JDK8 classes), I get the same issue. It is strange this issue has been there for so long time.

jbescos commented 1 year ago

I am comparing differences between com.sun.tools.ws.WsGen (this generates wrong xsd) and com.sun.tools.jxc.SchemaGenerator (this generates correct xsd). In both cases it reaches the same writer with different schema resolver:

From wsGen resolver is com.sun.xml.ws.wsdl.writer.WSDLGenerator$JAXWSOutputSchemaResolver@588ab592:

Thread [main] (Suspended)   
    org.glassfish.jaxb.runtime.v2.schemagen.XmlSchemaGenerator<T,C,F,M>.write(jakarta.xml.bind.SchemaOutputResolver, org.glassfish.jaxb.core.api.ErrorListener) line: 374   
    org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.generateSchema(jakarta.xml.bind.SchemaOutputResolver) line: 770   
    com.sun.xml.ws.db.glassfish.JAXBRIContextWrapper.generateSchema(jakarta.xml.bind.SchemaOutputResolver) line: 69 
    com.sun.xml.ws.wsdl.writer.WSDLGenerator.generateTypes() line: 423  
    com.sun.xml.ws.wsdl.writer.WSDLGenerator.generateDocument(com.sun.xml.txw2.output.XmlSerializer, com.sun.xml.txw2.output.XmlSerializer) line: 399   
    com.sun.xml.ws.wsdl.writer.WSDLGenerator.doGeneration() line: 285   
    com.sun.xml.ws.db.DatabindingImpl.generateWSDL(com.sun.xml.ws.api.databinding.WSDLGenInfo) line: 229    
    com.sun.tools.ws.wscompile.WsgenTool.buildModel(java.lang.String, com.sun.tools.ws.wscompile.WsimportListener) line: 303    
    com.sun.tools.ws.wscompile.WsgenTool.run(java.lang.String[]) line: 102  
    jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.lang.reflect.Method, java.lang.Object, java.lang.Object[]) line: not available [native method]   
    jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) line: 62 
    jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) line: 43 
    java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object...) line: 566    
    com.sun.tools.ws.Invoker.invoke(java.lang.String, java.lang.String[]) line: 132 
    com.sun.tools.ws.WsGen.main(java.lang.String[]) line: 29    

From schemagen resolver is com.sun.tools.jxc.ap.SchemaGenerator$1@436390f4:


Thread [main] (Suspended (breakpoint at line 374 in org.glassfish.jaxb.runtime.v2.schemagen.XmlSchemaGenerator))    
    org.glassfish.jaxb.runtime.v2.schemagen.XmlSchemaGenerator<T,C,F,M>.write(jakarta.xml.bind.SchemaOutputResolver, org.glassfish.jaxb.core.api.ErrorListener) line: 374   
    com.sun.tools.jxc.api.impl.j2s.JAXBModelImpl.generateSchema(jakarta.xml.bind.SchemaOutputResolver, com.sun.tools.xjc.api.ErrorListener) line: 156   
    com.sun.tools.jxc.ap.SchemaGenerator.process(java.util.Set<? extends javax.lang.model.element.TypeElement>, javax.annotation.processing.RoundEnvironment) line: 86  
    com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(javax.annotation.processing.Processor, java.util.Set<? extends javax.lang.model.element.TypeElement>, javax.annotation.processing.RoundEnvironment) line: 985   
    com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(java.util.Set<javax.lang.model.element.TypeElement>, com.sun.tools.javac.util.List<com.sun.tools.javac.code.Symbol.ClassSymbol>, com.sun.tools.javac.util.List<com.sun.tools.javac.code.Symbol.PackageSymbol>, com.sun.tools.javac.util.List<com.sun.tools.javac.code.Symbol.ModuleSymbol>) line: 901 
    com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(boolean, boolean) line: 1227    
    com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCCompilationUnit>, com.sun.tools.javac.util.List<com.sun.tools.javac.code.Symbol.ClassSymbol>, java.lang.Iterable<? extends com.sun.tools.javac.code.Symbol.PackageSymbol>, com.sun.tools.javac.util.Log.DeferredDiagnosticHandler) line: 1340    
    com.sun.tools.javac.main.JavaCompiler.processAnnotations(com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCCompilationUnit>, java.util.Collection<java.lang.String>) line: 1254   
    com.sun.tools.javac.main.JavaCompiler.compile(java.util.Collection<javax.tools.JavaFileObject>, java.util.Collection<java.lang.String>, java.lang.Iterable<? extends javax.annotation.processing.Processor>, java.util.Collection<java.lang.String>) line: 936  
    com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0() line: 104   
    com.sun.tools.javac.api.JavacTaskImpl$$Lambda$32.394714818.call() line: not available   
    com.sun.tools.javac.api.JavacTaskImpl.handleExceptions(java.util.concurrent.Callable<T>, T, T) line: 147    
    com.sun.tools.javac.api.JavacTaskImpl.doCall() line: 100    
    com.sun.tools.javac.api.JavacTaskImpl.call() line: 94   
    com.sun.tools.jxc.SchemaGenerator$Runner.compile(java.lang.String[], java.io.File) line: 251    
    jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.lang.reflect.Method, java.lang.Object, java.lang.Object[]) line: not available [native method]   
    jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) line: 62 
    jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) line: 43 
    java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object...) line: 566    
    com.sun.tools.jxc.SchemaGenerator.run(java.lang.String[], java.lang.ClassLoader) line: 152  
    com.sun.tools.jxc.SchemaGenerator.run(java.lang.String[]) line: 72  
jbescos commented 1 year ago

The problem is solved when I add the @XmlElementRef:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "")
@XmlRootElement(name = "generalCorrespondenceAddress")
public class GeneralCorrespondenceAddress implements Serializable {

    private final static long serialVersionUID = 1L;
    // Next fixes the issue
    @XmlElementRef
    protected AddressInformation addressInformation;
...
lukasj commented 1 year ago

jax-ws is passing defaultNamespaceRemap option to jaxb-ri in order to get default xml namespace in the to be generated schema updated and the problem is that jaxb-ri does not accept this command properly - https://github.com/eclipse-ee4j/jaxb-ri/issues/1715

will be fixed on the metro side once the new jaxb-ri version with the fix gets integrated

lukasj commented 1 year ago

fixed by #649