-, , , - . . , JSON XML, , schema validation. , , . null , , .., JAXBException, , , . , ExceptionMapper, . .
Address.java
@XmlRootElement(name = "address", namespace = DataEntity.NSP)
public class Address implements Serializable {
private static final long serialVersionUID = 2508433924387468026L;
private Integer id;
private String street;
private String number;
private Short zipCode;
private String city;
protected Address() {
}
public Address(final Integer id, final String street, final String number,
final Short zipCode, final String city) {
setId(id);
setStreet(street);
setNumber(number);
setZipCode(zipCode);
setCity(city);
}
@XmlAttribute
public Integer getId() {
return id;
}
private void setId(Integer id) {
ValidationHelper.validateId(id);
this.id = id;
}
@XmlElement(namespace = DataEntity.NSP)
public String getStreet() {
return street;
}
private void setStreet(String street) {
ValidationHelper.validateAddressStreet(street);
this.street = street;
}
@XmlElement(namespace = DataEntity.NSP)
public String getNumber() {
return number;
}
private void setNumber(String number) {
ValidationHelper.validateAddressNumber(number);
this.number = number;
}
@XmlElement(namespace = DataEntity.NSP)
public Short getZipCode() {
return zipCode;
}
private void setZipCode(Short zipCode) {
ValidationHelper.validateAddressZipCode(zipCode);
this.zipCode = zipCode;
}
@XmlElement(namespace = DataEntity.NSP)
public String getCity() {
return city;
}
private void setCity(String city) {
ValidationHelper.validateAddressCity(city);
this.city = city;
}
}
:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="https://localhost/JAX-RS_BookStore_Service/xsd/" targetNamespace="https://localhost/JAX-RS_BookStore_Service/xsd/"
elementFormDefault="qualified" xmlns:pref="https://localhost/JAX-RS_BookStore_Service/xsd/">
<xs:include schemaLocation="Types.xsd" />
<xs:element name="address" type="addressType" />
</xs:schema>
xsd:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="https://localhost/JAX-RS_BookStore_Service/xsd/"
targetNamespace="https://localhost/JAX-RS_BookStore_Service/xsd/"
elementFormDefault="qualified" xmlns:pref="https://localhost/JAX-RS_BookStore_Service/xsd/">
<xs:simpleType name="unsignedInteger">
<xs:restriction base="xs:integer">
<xs:minInclusive value="1" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="addressStreet">
<xs:restriction base="xs:string">
<xs:pattern value="[a-zA-ZöäüÖÄÜß -]{2,32}" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="addressNumber">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9]{1}[0-9a-z/\\ -]{0,7}" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="addressCity">
<xs:restriction base="xs:string">
<xs:pattern value="[a-zA-ZöäüÖÄÜß -]{2,32}" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="zipCodeMoreThan4Digits">
<xs:restriction base="xs:short">
<xs:minInclusive value="1000"></xs:minInclusive>
<xs:maxInclusive value="9999"></xs:maxInclusive>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="addressType">
<xs:sequence>
<xs:element name="city" type="addressCity" />
<xs:element name="number" type="addressNumber" />
<xs:element name="street" type="addressStreet" />
<xs:element name="zipCode" type="zipCodeMoreThan4Digits" />
</xs:sequence>
<xs:attribute name="id" type="unsignedInteger" use="required">
</xs:attribute>
</xs:complexType>
</xs:schema>
MessageBodyReader, . XML .
public abstract class AbstractXmlValidationReader<T> implements
MessageBodyReader<T> {
private final Providers providers;
private final Schema schema;
public AbstractXmlValidationReader(final Providers providers,
final ServletContext servletContext, final String xsdFileName) {
this.providers = providers;
try {
SchemaFactory sf = SchemaFactory
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
File xsd = new File(servletContext.getRealPath(xsdFileName));
schema = sf.newSchema(xsd);
} catch (Exception e) {
throw new RuntimeException(
"Unable to create XSD validation schema", e);
}
}
@Override
public boolean isReadable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
@SuppressWarnings("unchecked")
Class<T> readableClass = (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
if (type == readableClass
&& type.isAnnotationPresent(XmlRootElement.class)) {
return true;
}
return false;
}
@Override
public T readFrom(Class<T> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
throws IOException, WebApplicationException {
try {
JAXBContext jaxbContext = null;
ContextResolver<JAXBContext> resolver = providers
.getContextResolver(JAXBContext.class, mediaType);
if (null != resolver) {
jaxbContext = resolver.getContext(type);
}
if (null == jaxbContext) {
jaxbContext = JAXBContext.newInstance(type);
}
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller.setSchema(schema);
@SuppressWarnings("unchecked")
T entity = (T) unmarshaller.unmarshal(entityStream);
return entity;
} catch (JAXBException e) {
throw new MessageBodyReaderValidationException(
"Failure while performing xml validation or xml marhalling!",
e);
}
}
}
MeassagBodyReader, XSD .
@Provider
@Consumes(MediaType.APPLICATION_XML)
public class AddressXmlValidationReader extends
AbstractXmlValidationReader<Address> {
private final static String xsdFileName = "/xsd/Address.xsd";
public AddressXmlValidationReader(@Context Providers providers,
@Context ServletContext servletContext) {
super(providers, servletContext, xsdFileName);
}
}
, , ExceptionMapper. . , sth. , HTML.
Application ! classes.add(MessageBodyReaderValidationExceptionMapper.class);
@Provider
public class MessageBodyReaderValidationExceptionMapper implements
ExceptionMapper<MessageBodyReaderValidationException> {
@Override
public Response toResponse(MessageBodyReaderValidationException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(e.getMessage()).type(MediaType.TEXT_PLAIN).build();
}
}
POST Firefox RESTClient.
, <street> , null !
