2012-02-02 11 views
15

Documentación para required dice:¿Cuál es el propósito de minOccurs, nillable y restricción?

Si required() es true, entonces propiedad Javabean se asigna a un esquema XML elemento declaración con . maxOccurs es "1" para una sola propiedad con valor y "unbounded" para una propiedad con varios valores.

Si required() es false, entonces la propiedad Javabean se asigna a XML declaración de elemento de esquema con minOccurs="0". maxOccurs es "1" para una propiedad de un solo valor y "unbounded" para una propiedad de varios valores.

Documentación para nillable dice:

Si es nillable()true, entonces la propiedad JavaBean se asigna a un esquema XML nillable declaración de elemento.


Código de 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; 
    } 
} 

Código de 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; 
} 

generada esquema 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> 


Los hechos:

  1. El valor por defecto para minOcurrencias es 1. Por lo tanto, se requiere meses (debe existir);
  2. El mes tiene una restricción . Por lo tanto, mes solo puede tener un valor definido por una de las 12 enumeraciones definidas;
  3. El valor predeterminado para nillable es falso. Por lo tanto, mes no puede tener valores vacíos;
  4. El esquema XML se genera correctamente.

Los problemas:

  1. Es aceptar abcense del mes (no debe existir);
  2. Acepta cualquier valor para el mes, como 13 (excepto cuando no se puede analizar en Entero);
  3. Acepta valores vacíos;

No esperaba estos problemas, ¿me falta algo?
Si ese comportamiento es correcto, lo que es el propósito de required, nillable y xs:restriction?

Respuesta

9

Nillable permite valores vacíos. Por ejemplo, si tiene un Entero o una Fecha, si es anulable, la etiqueta XML podría estar vacía. Si no es anulable pero no es obligatorio, el elemento XML debería existir con un contenido válido o no existir; una etiqueta vacía no sería válida.

+0

¿Quiere decir que nillable se utiliza para definir si puede tener valores vacíos cuando existe la etiqueta; y eso requerido se usa para definir si la etiqueta debe existir o no? En este caso, ¿por qué está permitiendo etiquetas vacías y por qué no requiere tener esa etiqueta? ¿Cómo anoto para hacer minOccurs 1? – falsarella

+0

minOccurs es 1 por defecto. Su esquema original dice que ese mes es obligatorio (la etiqueta existe y no está vacía). – bcody

+0

¿Entonces por qué acepta abcense de mes o valor vacío? ¡No genera un error en la respuesta! – falsarella

5

Realice minOccurs 1, para que el mes sea necesario;

El valor predeterminado para minOccurs es uno, por lo que se requiere el elemento month. Observe cómo se tuvo que agregar minOccurs="0" al userLogin para hacerlo opcional.

<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> 

Validar mes con su restricción generado (sin XmlAdapter).

Puede configurar una instancia de Schema en el Unmarshaller de tener la entrada validado:

demostración

El código siguiente se puede utilizar para generar el esquema 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(); 
    } 

} 

ACTUALIZACIÓN

El JAXB RI tiros normalmente un ValidationEvent de gravedad 1 para problemas de conversión. El valor predeterminado ValidationEventHandler ignora todos los problemas de gravedad inferiores a 2. Esto normalmente da como resultado que el valor se establezca como nulo. Puede anular la ValidationEventHandler de la siguiente manera:

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

Sin embargo, el JAXB RI no aparecen a tirar eventos relacionados con la conversión de los valores de enumeración (posible de errores).Si sucede utilizar EclipseLink JAXB (moxy) como su proveedor de JAXB por lo que recibirá una excepción como:

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) 

Para más información

+0

Si se requiere un mes, ¿por qué acepta la ausencia nula o el mes (0 ocurrencias)? – falsarella

+0

Acerca de cómo generar el esquema ... Lo que sé sobre la generación es que es automática aquí ... En el arranque de JBoss, algo lo crea dado el mapeo web.xml y las anotaciones de WebService y XmlXXX, y eso es todo. Por cierto, supongo que ese no es el punto, mi xsd se está generando correctamente. Pero acepta 13 como entrada para el mes (sin clasificar a nulo), por ejemplo. Además, acepta nulo y su ausencia. ¿Por qué? Crear una restricción de enumeraciones y no crear me dará el mismo comportamiento de aceptación. – falsarella

+0

Descubrí que puedo crear un método afterUnmarshal para manejar null, por ejemplo, y funciona, pero ¿para qué sirve poner algo con minOccurs 1 en xsd si acepta 0 ocurrencias y cuál es el propósito de crear una restricción (con enum)? si no se valida si el valor de entrada está en ese 'rango'? – falsarella

4

Los propósitos de required y minOccurs no son engañosas, el problema es que la validación del esquema no está habilitada. Sólo permitenSchemaValidation a la WebService y definir el orden del XmlType 's mapeo de la siguiente manera: Servicio

Web:

@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

De hecho, parece que los sobres SOAP no se validan en WSDL, ni en el servidor ni en el cliente.

Y creo que es mejor así. La validación consume recursos y tiempo. Para la mayoría de los servicios web, todo lo que necesitamos con WSDL es proporcionar al cliente las definiciones para poder hablar con WebService, y no establecer restricciones como si una propiedad puede o no ser nula.

Cuando el servidor y el cliente están en la misma PC, Axis2 agrega 3-5 milisegundos de sobrecarga en comparación con las llamadas internas. La validación innecesaria solo aumentaría la sobrecarga. Es mejor hacer que las operaciones arrojen una excepción y validen manualmente lo que realmente se necesita.

1

Miré en la estructura XSD que ha publicado, y descubro que no ha utilizado el tipo complejo que ha definido para el mes, Insteqad de manejarlo en código Java puede mencionarlo todo en XSD, y también el minOccur en el mes - falta el elemento en su tipo complejo. Por favor utilice cualquier XSD standered al generador Java, lo hará toda la tarea de generación de archivos java para que

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> 
Cuestiones relacionadas