jaxbcontext генерирует неполные схемы? - PullRequest
2 голосов
/ 10 января 2012

Я столкнулся со странной проблемой с JAXB. Я использовал xjc для генерации Java-классов из моего XSD, и все выглядит хорошо. Если я использую schemagen, он создаст правильную схему, которая соответствует моему исходному xsd. Однако если я использую JAXBContext.generateSchema (), сгенерированная схема будет неполной.

Я использую Oracle Java 1.6.0_29 и jaxb-2.2.4-1.jar в качестве реализации. Я прилагаю код Java (который генерирует схему), и xsd ниже, а также вывод вызова jaxb.

CalculateBorrowingDataResponse.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema 
    version="1.1"
    attributeFormDefault="unqualified" 
    elementFormDefault="qualified"
    targetNamespace="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse" 
    xmlns:lssSt="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse"
    xmlns:cbdRes="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">


    <!-- CalculateBorrowingData -->
    <xsd:complexType name="CalculateBorrowingDataResponseType">
        <xsd:sequence>
            <xsd:element name="loanAgmt" type="cbdRes:LoanAgreementType" minOccurs="1" maxOccurs="1" />
        </xsd:sequence>
    </xsd:complexType>


    <xsd:complexType name="LoanAgreementType">
        <xsd:sequence>
            <xsd:element name="borrowingBasedPmtAmt" type="lssSt:borrowingBasedPmtAmt" minOccurs="0" maxOccurs="1" />
            <xsd:element name="maxPmtAmt" type="lssSt:maxPmtAmt" minOccurs="0" maxOccurs="1" />
            <xsd:element name="borrowingCapacityMin" type="lssSt:borrowingCapacityMin" minOccurs="0" maxOccurs="1" />
            <xsd:element name="borrowingCapacityMax" type="lssSt:borrowingCapacityMax" minOccurs="0" maxOccurs="1" />
            <xsd:element name="propertyValueMinAmt" type="lssSt:propertyValueMinAmt" minOccurs="0" maxOccurs="1" />
            <xsd:element name="propertyValueMaxAmt" type="lssSt:propertyValueMaxAmt" minOccurs="0" maxOccurs="1" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:element name="calculateBorrowingDataResponse" type="cbdRes:CalculateBorrowingDataResponseType"/>


    <xsd:simpleType name="borrowingBasedPmtAmt">
        <xsd:restriction base="xsd:decimal" >
        <xsd:totalDigits value="19" />
        <xsd:fractionDigits value="4" />
        </xsd:restriction>
    </xsd:simpleType>
    <xsd:simpleType name="maxPmtAmt">
        <xsd:restriction base="xsd:decimal" >
        <xsd:totalDigits value="19" />
        <xsd:fractionDigits value="4" />
        </xsd:restriction>
    </xsd:simpleType>
    <xsd:simpleType name="borrowingCapacityMin">
        <xsd:restriction base="xsd:decimal" >
        <xsd:totalDigits value="19" />
        <xsd:fractionDigits value="4" />
        </xsd:restriction>
    </xsd:simpleType>
    <xsd:simpleType name="borrowingCapacityMax">
        <xsd:restriction base="xsd:decimal" >
        <xsd:totalDigits value="19" />
        <xsd:fractionDigits value="4" />
        </xsd:restriction>
    </xsd:simpleType>
    <xsd:simpleType name="propertyValueMinAmt">
        <xsd:restriction base="xsd:decimal" >
        <xsd:totalDigits value="19" />
        <xsd:fractionDigits value="4" />
        </xsd:restriction>
    </xsd:simpleType>
    <xsd:simpleType name="propertyValueMaxAmt">
        <xsd:restriction base="xsd:decimal" >
        <xsd:totalDigits value="19" />
        <xsd:fractionDigits value="4" />
        </xsd:restriction>
    </xsd:simpleType>

</xsd:schema>

Java-код:

    // Creating the XML tree
    JAXBContext jc = JAXBContext.newInstance( CalculateBorrowingDataResponseType.class );
    Unmarshaller u = jc.createUnmarshaller();

    // generate the schemas
    final List<ByteArrayOutputStream> schemaStreams = new ArrayList<ByteArrayOutputStream>();
    jc.generateSchema(new SchemaOutputResolver(){
        @Override
        public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            schemaStreams.add(out);
            StreamResult streamResult = new StreamResult(out);
            streamResult.setSystemId("");
            return streamResult;
        }});

    // convert to a list of string
    List<String> schemas = new ArrayList<String>();
    for( ByteArrayOutputStream os : schemaStreams )
    {
        schemas.add(os.toString());
        System.out.println( os.toString());
    }

Вывод jaxbContext.generateSchema ():

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema elementFormDefault="qualified" version="1.0" targetNamespace="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse" xmlns:tns="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:complexType name="CalculateBorrowingDataResponseType">
    <xs:sequence>
      <xs:element name="loanAgmt" type="tns:LoanAgreementType"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="LoanAgreementType">
    <xs:sequence>
      <xs:element name="borrowingBasedPmtAmt" type="xs:decimal" minOccurs="0"/>
      <xs:element name="maxPmtAmt" type="xs:decimal" minOccurs="0"/>
      <xs:element name="borrowingCapacityMin" type="xs:decimal" minOccurs="0"/>
      <xs:element name="borrowingCapacityMax" type="xs:decimal" minOccurs="0"/>
      <xs:element name="propertyValueMinAmt" type="xs:decimal" minOccurs="0"/>
      <xs:element name="propertyValueMaxAmt" type="xs:decimal" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

Как видите, схема вывода очень близко совпадает, сохраните и за исключением того, что в ней отсутствует определение элемента CalculateBorrowingDataResponse! Если я использую schemagen, однако, Элемент CalculateBorrowingDataResponse создан.

Я что-то упустил в настройке SchemaOutputResolver или сделал что-то неверное / неполное? Или это ошибка в Jaxb RI?

Ответы [ 3 ]

6 голосов
/ 10 января 2012

Изменить

JAXBContext.newInstance(CalculateBorrowingDataResponseType.class);

на

JAXBContext.newInstance(CalculateBorrowingDataResponseType.class.getPackage().getName());

JAXB требуется информация, определенная в файле package-info.java (сгенерированном xjc из вашего XSD) внутри пакета вышеупомянутого класса.

Он не создает рассматриваемый элемент XSD, потому что CalculateBorrowingDataResponseType не имеет аннотации @XmlRootElement.

Почему xjc не создал его с самого начала?См. самое авторитетное объяснение в Интернетах по этому вопросу .

И почему ваш код генерирует вышеупомянутый элемент, если вы предоставляете имя пакета для JAXBContext.newInstance(...) дажехотя CalculateBorrowingDataResponseType все еще отсутствует @XmlRootAnnotation? У меня нет ни малейшего представления! Теперь у меня есть!

5 голосов
/ 11 января 2012

Следующее из сгенерированного класса ObjectFactory - это то, что заставляет этот элемент генерироваться:

@XmlElementDecl(namespace = "http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse", name = "calculateBorrowingDataResponse")
public JAXBElement<CalculateBorrowingDataResponseType> createCalculateBorrowingDataResponse(CalculateBorrowingDataResponseType value) {
    return new JAXBElement<CalculateBorrowingDataResponseType>(_CalculateBorrowingDataResponse_QNAME, CalculateBorrowingDataResponseType.class, null, value);
}

Чтобы класс ObjectFactory обрабатывался JAXBContext, вам нужно либо включить его в массивклассов, переданных для создания JAXBContext:

JAXBContext jc = JAXBContext.newInstance(CalculateBorrowingDataResponseType.class, ObjectFactory.class);

Или для создания JAXBContext по имени пакета сгенерированных классов:

String contextPath = CalculateBorrowingDataResponseType.class.getPackage().getName();
JAXBContext jc = JAXBContext.newInstance(contextPath);

Полный пример

package forum8809406;

import java.io.IOException;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.SchemaOutputResolver;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance("forum8809406");
        jc.generateSchema(new SOR());
    }

    private static class SOR extends SchemaOutputResolver {

        @Override
        public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
            StreamResult result = new StreamResult(System.out);
            result.setSystemId(suggestedFileName);
            return result;
        }

    }

}

Я получаю следующую сгенерированную схему XML, которая содержит элемент calculateBorrowingDataResponse:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema 
    version="1.0" 
    elementFormDefault="qualified" 
    targetNamespace="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse" 
    xmlns:tns="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:complexType name="CalculateBorrowingDataResponseType">
    <xs:sequence>
      <xs:element name="loanAgmt" type="tns:LoanAgreementType"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="LoanAgreementType">
    <xs:sequence>
      <xs:element name="borrowingBasedPmtAmt" type="xs:decimal" minOccurs="0"/>
      <xs:element name="maxPmtAmt" type="xs:decimal" minOccurs="0"/>
      <xs:element name="borrowingCapacityMin" type="xs:decimal" minOccurs="0"/>
      <xs:element name="borrowingCapacityMax" type="xs:decimal" minOccurs="0"/>
      <xs:element name="propertyValueMinAmt" type="xs:decimal" minOccurs="0"/>
      <xs:element name="propertyValueMaxAmt" type="xs:decimal" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:element name="calculateBorrowingDataResponse" type="tns:CalculateBorrowingDataResponseType"/>
</xs:schema>
0 голосов
/ 10 января 2012

Почему вы думаете, что в циклическом 'schema1-> XJC-> schema2' schema1 и schema 2 должны быть идентичны?Есть ли у вас Java-класс, сгенерированный для элемента «возбудить вычисления» в XJC?Я так не думаю - как вы ожидаете, что это будет в сгенерированной схеме тогда?

...