Showing posts with label XSD and JAVA. Show all posts
Showing posts with label XSD and JAVA. Show all posts

Monday, December 31, 2012

XML-to-Java mappings used by JAX-WS

In this post i am not going to discuss more details on XML-to-Java object mapping used by JAX-WS.

I will describe, when JAX-WS maps, XML element or attribute declaration to Java primitive wrapper class. Most of the time, during designing/writing schema definition(XSD) for web service, we are not thinking about that XML-to-Java conversion, hence later on it will become a issue while debugging web service.

There are mainly three conditions when XML element or attribute declaration converted to Java primitive wrapper class used by JAX-WS.

  1. When element declaration contains "minCccurs=0" attribute.
  2. When element declaration contains "nillable=true" attribute.
  3. When attribute declaration contains "use=optional" attribute. 
Examples:





In the above element/attribute declaration "short/boolean" primitive datatype is converted to "short/boolean" primitive wrapper class.

Sunday, November 25, 2012

How to hide/expose namespace from element in XSD

Whenever we are talking about XSD(Schema defination), we are using namespace. Basically what is namespace? and why it is required. Is is possible to hide the namespace from element name.

This post answer all those questions.

namespace - namespaces are using to avoid element name conflicts. If you have little bit knowledge of SQL then you can understand it better way. Suppose you have two tables like 'Employee' and 'Department' and you are trying to join two table to get the employee name, employee id, department name and department id. In this case, you query should be:

select ename, department_name, id, id from Employee e, Department d where e.dept_no=d.id;

In this query there is an issue. In the select we have written two id column, but it is not clear which table's id column it is, so there is a name conflict. In this case you have to prefix the table alias. So, that it is understandable.

So, it is possible to define two element with the same name with different namespace. namespaces are declare at the begining of schema defination.





In the above example, you can see the attribute name "xmlns", this attribute is used to define XML namespace. The namespace are declared using ":" colon. The text after the ":" is called a namespace.

If keyword "xmlns" define alone with a value of http://www.w3.org/2001/XMLSchema, is called default namespace.

Basically default namespace defines the rules and regulations for the schema.

you can refer other schemas using the keyword "xmlns" prefix with the namespace name, like the above example i have refer globaltypes using the "xmlns:gtns". Later on you can simply use the namespace name before the element name.

I hope from the above discussion, you have understand what is "namespace" and why it is required.

Now, the only question remains is "Can we hide namespace name from element name?" answer is Yes.

If you closely look the above code snipet of schema defination, you found there is another attribute i.e "elementFromDetault". Basically this attibute handles to hide/unhide the namespace from the element name.

Example:
If you use the above declaration for the schema, you will get the below:

Unqualified version:
 In the above example you can see the element name is not prefix with namespace.

Qualified version:









 In the above example you can see the element name is prefix with namespace.

Hence, you can say using the attribut "elementFromDefault" you can hide/unhide namespace from the element.

Tuesday, July 5, 2011

Validate JAXB Object with XML Schema

We can validate JAXB Object with XML Schema(XSD). JAXB provide a class named Validator to validate against a schema. This class is available since Java 1.5


package javawiki.jaxb.validation;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlRootElement
@XmlType(name = "Customer", propOrder = {
"name",
"phoneNumber",
})
public class Customer {

private String name;
private List phoneNumber;

public Customer() {
phoneNumber = new ArrayList();
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public List getPhoneNumber() {
return phoneNumber;
}

public void setPhoneNumber(List phoneNumber) {
this.phoneNumber = phoneNumber;
}
}

package javawiki.jaxb.validation;

public class PhoneNumber {

}


<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xs:element name="customer">
  <xs:complexType>
   <xs:sequence>
    <xs:element name="name" type="stringMaxSize5" />
    <xs:element ref="phoneNumber" maxOccurs="3" />
   </xs:sequence>
  </xs:complexType>
 </xs:element>

 <xs:element name="phoneNumber">
  <xs:complexType />
 </xs:element>

 <xs:simpleType name="stringMaxSize5">
  <xs:restriction base="xs:string">
   <xs:maxLength value="5" />
  </xs:restriction>
 </xs:simpleType>

</xs:schema>


package javawiki.jaxb.validation;

import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

public class MyErrorHandler implements ErrorHandler {

 @Override
 public void error(SAXParseException exception) throws SAXException {
  System.out.println(exception.getLocalizedMessage());
 }

 @Override
 public void fatalError(SAXParseException exception) throws SAXException {
  System.out.println(exception.getLocalizedMessage());
 }

 @Override
 public void warning(SAXParseException exception) throws SAXException {
  System.out.println(exception.getLocalizedMessage());
 }

}


package javawiki.jaxb.validation;

import java.io.File;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.util.JAXBSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

public class DemoSchemaValidation {

 public static void main(String[] args) {
  Customer customer = new Customer();
        customer.setName("Jane ");
        customer.getPhoneNumber().add(new PhoneNumber());
        customer.getPhoneNumber().add(new PhoneNumber());
        customer.getPhoneNumber().add(new PhoneNumber());
        
        try
        {
         JAXBContext jc = JAXBContext.newInstance(Customer.class);
         JAXBSource source = new JAXBSource(jc, customer);
 
         SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
         Schema schema = sf.newSchema(new File("src/javawiki/jaxb/validation/customer.xsd")); 
 
         Validator validator = schema.newValidator();
         validator.setErrorHandler(new MyErrorHandler());
         validator.validate(source);
        }catch(Exception ex)
        {
         ex.printStackTrace();
        }
 }

}

Output:
cvc-maxLength-valid: Value 'Jane Doe' with length = '8' is not facet-valid with respect to maxLength '5' for type 'stringMaxSize5'.
cvc-type.3.1.3: The value 'Jane Doe' of element 'name' is not valid.
cvc-complex-type.2.4.d: Invalid content was found starting with element 'phoneNumber'. No child element is expected at this point.

Thursday, October 7, 2010

Generate Java Class from XSD

XSD stands for XML Schema Defination. This is the alternative of old DTD.

An XML Schema can:
•defines elements that can appear in a document
•defines attributes that can appear in a document
•defines which elements are child elements
•defines the order of child elements
•defines the number of child elements
•defines whether an element is empty or can include text
•defines data types for elements and attributes
•defines default and fixed values for elements and attributes

XSD will be used in most of the Web Applications instead of DTD for the following reasions:
•XML Schemas are extensible to future additions
•XML Schemas are richer and more powerful than DTDs
•XML Schemas are written in XML
•XML Schemas support data types
•XML Schemas support namespaces

Simple Structure of XSD:
File name is schema.xsd.


There are number of ways/tools that will generate java class from XSD. One of them is xjc given by Sun Java Web Service Developers Pack.
This is the command line tool.
To generate the java class enter the statement in command prompt.
C:\xjc schema.xsd -d .
This command generates:

package generated;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;


/**
*

Java class for anonymous complex type.
*
*

The following schema fragment specifies the expected content contained within this class.
*
*


* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="userName" type="{http://www.w3.org/2001/XMLSchema}string"/>
* <element name="password" type="{http://www.w3.org/2001/XMLSchema}string"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
*

*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"userName",
"password"
})
@XmlRootElement(name = "LoginBn")
public class LoginBn {

@XmlElement(required = true)
protected String userName;
@XmlElement(required = true)
protected String password;

/**
* Gets the value of the userName property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getUserName() {
return userName;
}

/**
* Sets the value of the userName property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setUserName(String value) {
this.userName = value;
}

/**
* Gets the value of the password property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getPassword() {
return password;
}

/**
* Sets the value of the password property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setPassword(String value) {
this.password = value;
}

}