Какова цель minOccurs, nillable и ограничения? - PullRequest
15 голосов
/ 02 февраля 2012

Документация для требуется говорит:

Если required() true, тогда свойство Javabean сопоставляется с элементом схемы XML объявление с minOccurs="1". maxOccurs равно "1" для одного значения свойство и "unbounded" для многозначного свойства.

Если required() равно false, то свойство Javabean сопоставляется с XML Объявление элемента схемы с minOccurs="0". maxOccurs составляет "1" для однозначное свойство и "unbounded" для многозначного свойства.

Документация для nillable говорит:

Если nillable() равно true, то свойство JavaBean сопоставляется с XML Схема nillable объявление элемента.

<ч /> Код для xs:complexType:

public class WSData {
    //...

    @XmlElement(required = true, nillable = false)
    public void setMonth(XmlMonthType month) {
        this.month = month;
    }

    public void setUserLogin(String userLogin) {
        this.userLogin = userLogin;
    }
}

Код для xs:simpleType:

@XmlType
@XmlEnum(Integer.class)
public enum XmlMonthType {
    @XmlEnumValue("1")
    JANUARY,
    @XmlEnumValue("2")
    FEBRUARY,
    @XmlEnumValue("3")
    MARCH,
    /* ... months 4 ~9 ... */
    @XmlEnumValue("10")
    OCTOBER,
    @XmlEnumValue("11")
    NOVEMBER,
    @XmlEnumValue("12")
    DECEMBER;
}
<Ч />

Сгенерированная XML-схема:

<xs:complexType name="wsData">
  <xs:sequence>
    <xs:element name="month" type="xs:string"/>
    <xs:element minOccurs="0" name="userLogin" type="xs:string"/>
  </xs:sequence>
</xs:complexType>

<xs:simpleType name="xmlMonthType">
  <xs:restriction base="xs:int">
    <xs:enumeration value="1"/>
    <xs:enumeration value="2"/>
    <xs:enumeration value="3"/>
    <!-- ... months 4 ~9 ... -->
    <xs:enumeration value="10"/>
    <xs:enumeration value="11"/>
    <xs:enumeration value="12"/>
  </xs:restriction>
</xs:simpleType>

<ч /> Факты:

  1. Значение по умолчанию для minOccurs равно 1. Итак, month требуется (должно существовать);
  2. Месяц имеет ограничение . Таким образом, month может иметь значение, определенное только одним из 12 определенных перечислений;
  3. Значение по умолчанию для nillable равно false. Итак, month не может иметь пустых значений;
  4. Схема XML сгенерирована правильно.

Проблемы:

  1. Принимает месяц отсутствия (не должно существовать);
  2. Он принимает любые значения за месяц, например, 13 (кроме случаев, когда он не разбирается в Integer);
  3. Принимает пустые значения;

Я не ожидал этих проблем, я что-то упустил?
Если это поведение правильное, для чего нужно требуется , nillable и xs: ограничение

Ответы [ 5 ]

9 голосов
/ 02 февраля 2012

Nillable допускает пустые значения.Например, если у вас есть целочисленное значение или дата, если она пустая, тег XML может быть пустым.Если это не nillable, но не требуется, элемент XML должен либо существовать с допустимым содержимым, либо вообще не существовать;пустой тег недействителен.

5 голосов
/ 02 февраля 2012

Сделать minOccurs 1, чтобы сделать месяц обязательным;

Значение по умолчанию для minOccurs равно единице, поэтому требуется элемент month.Обратите внимание, как minOccurs="0" необходимо было добавить к userLogin, чтобы сделать его необязательным.

<xs:complexType name="wsData">
  <xs:sequence>
    <xs:element name="month" type="xs:string"/>
    <xs:element minOccurs="0" name="userLogin" type="xs:string"/>
  </xs:sequence>
</xs:complexType>

Проверка месяца с его сгенерированным ограничением (без XmlAdapter).

Вы можете установить экземпляр Schema в Unmarshaller, чтобы подтвердить ввод:

Демо

Следующий код может использоваться для генерации схемы XML:

package forum9111936;

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(WSData.class);
        SchemaOutputResolver sor = new SchemaOutputResolver() {

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

        };
        jc.generateSchema(sor);
        System.out.println();
    }

}

ОБНОВЛЕНИЕ

RI JAXB обычно выбрасывает ValidationEvent серьезности 1 для проблем преобразования.Значение по умолчанию ValidationEventHandler игнорирует все проблемы с серьезностью меньше 2. Это обычно приводит к тому, что значение устанавливается равным нулю.Вы можете переопределить ValidationEventHandler следующим образом:

    unmarshaller.setEventHandler(new ValidationEventHandler() {
        @Override
        public boolean handleEvent(ValidationEvent event) {
            System.out.println(event);
            return event.getSeverity() < ValidationEvent.ERROR;
        }
    });

Однако JAXB RI не отображает события, связанные с преобразованием значений перечисления (возможная ошибка).Если вы используете EclipseLink JAXB (MOXy) в качестве поставщика JAXB, вы получите исключение, например:

Exception in thread "main" Local Exception Stack: 
Exception [EclipseLink-116] (Eclipse Persistence Services - 2.4.0.qualifier): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: No conversion value provided for the value [13] in field [month/text()].
Mapping: org.eclipse.persistence.oxm.mappings.XMLDirectMapping[month-->month/text()]
Descriptor: XMLDescriptor(forum9111936.WSData --> [])
    at org.eclipse.persistence.exceptions.DescriptorException.noFieldValueConversionToAttributeValueProvided(DescriptorException.java:1052)
    at org.eclipse.persistence.mappings.converters.ObjectTypeConverter.convertDataValueToObjectValue(ObjectTypeConverter.java:140)
    at org.eclipse.persistence.oxm.mappings.XMLDirectMapping.getAttributeValue(XMLDirectMapping.java:287)
    at org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue.endElement(XMLDirectMappingNodeValue.java:190)
    at org.eclipse.persistence.oxm.record.UnmarshalRecord.endElement(UnmarshalRecord.java:910)
    at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parseEvent(XMLStreamReaderReader.java:133)
    at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parse(XMLStreamReaderReader.java:83)
    at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parse(XMLStreamReaderReader.java:72)
    at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:838)
    at org.eclipse.persistence.oxm.XMLUnmarshaller.unmarshal(XMLUnmarshaller.java:626)
    at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:472)
    at forum9111936.Demo2.main(Demo2.java:30)

Для получения дополнительной информации

4 голосов
/ 17 февраля 2012

Цели required и minOccurs не вводят в заблуждение, проблема в том, что проверка схемы не включена. Просто разрешить SchemaValidation до WebService и определить порядок из XmlType ' S отображение следующим образом:

Веб-сервис:

@javax.jws.WebService
@org.jboss.ws.annotation.SchemaValidation(enabled = true)
public class WebServiceClass {

    @javax.jws.WebMethod
    public WSResponseData webServiceMethod() {
        //...
    }
}

XmlType:

@javax.xml.bind.annotation.XmlType(propOrder = {"field1", "field2", "field3"})
public class WSData {
    //...

    private String field1;

    private Long field2;

    private XmlMonthType field3;

    //...
}
1 голос
/ 11 июля 2016

Я посмотрел на структуру XSD, которую вы опубликовали, и обнаружил, что вы не использовали сложный тип, который вы определили в течение месяца. В Insteqad для обработки его с помощью кода Java вы можете упомянуть, что все в XSD, а также minOccurна месяц - элемент в вашем сложном типе отсутствует.Пожалуйста, используйте любой стандартный XSD для генератора java, он выполнит все задачи по созданию файла java для вас

The convention are as follow - 

MinOccur = 0 --> the element can be abscent in input , and can be present

MinOccur = 1 --> the element must be there in input
(but if you use it, then your java generated member will be of list type - list of ENUM for Int )

If you don't write MinOccur in attributes - then it makes the element mandatory , ( then you java generated member will be of simply ENUM for int )


MaxOccur = 1 --> minimum one element can be there in input 
(but if you use it, then your java generated member will be of list type - list of ENUM for Int )


MaxOccur = unbound --> only one element can be there in input 
(if you use it, then your java generated member will be of list type - list of ENUM for Int )

   <xs:complexType name="wsData">
  <xs:sequence>
    <xs:element name="month" type="xmlMonthType" minOccurs="1" nillable="false" />
    <xs:element name="userLogin" type="xs:string" minOccurs="0" />
  </xs:sequence>
</xs:complexType>

<xs:simpleType name="xmlMonthType">
  <xs:restriction base="xs:int">
    <xs:enumeration value="1"/>
    <xs:enumeration value="2"/>
    <xs:enumeration value="3"/>
    <!-- ... months 4 ~9 ... -->
    <xs:enumeration value="10"/>
    <xs:enumeration value="11"/>
    <xs:enumeration value="12"/>
  </xs:restriction>
</xs:simpleType>
1 голос
/ 22 февраля 2013

Действительно, кажется, что конверты SOAP не проверяются на WSDL, ни на сервере, ни на клиенте.

И я думаю, что так будет лучше.Валидация требует ресурсов и времени.Для большинства WebServices все, что нам нужно с WSDL, - это предоставить клиенту определения, чтобы иметь возможность общаться с WebService, а не устанавливать ограничения, например, может ли свойство иметь значение NULL или нет.Тот же ПК, Axis2 добавляет 3-5 миллисекунд накладных расходов по сравнению с внутренними вызовами.Излишняя проверка только увеличит накладные расходы.Лучше, чтобы операции генерировали исключение и вручную проверяли, что действительно нужно.

...