Web Services Material - Sriman Latest PDF
Web Services Material - Sriman Latest PDF
Web Services Material - Sriman Latest PDF
Web Services
JAX-RPC, JAX-WS & JAX-RS
Mr. Sriman
As part of this we are going to cover Web Services and its related technologies like
XML, XSD, DTD, JAX-P, JAX-B, JAX-RPC, JAX-WS, and JAX-RS etc. Provides an in-
depth understanding of each including the examples.
Mr. Sriman Web Services
1
Mr. Sriman Web Services
Contents
1 INTRODUCTION ..................................................................................................... 8
2 EVOLUTION .......................................................................................................... 14
2.1 JAVA API’S FOR WS-I SPECIFICATION......................................................................... 15
3 ARCHITECTURE .................................................................................................... 16
3.1 MEDIUM ............................................................................................................ 16
3.2 PROTOCOL .......................................................................................................... 16
3.3 LANGUAGE.......................................................................................................... 17
3.4 BINDING PROTOCOL .............................................................................................. 18
3.5 WSDL (WEB SERVICE DESCRIPTION LANGUAGE) ........................................................... 19
3.6 UDDI (UNIVERSAL DESCRIPTION AND DISCOVERY INTEGRATION REGISTRY)............................ 20
4 XML ...................................................................................................................... 23
5 DTD ...................................................................................................................... 26
2
Mr. Sriman Web Services
8 JAX-P ................................................................................................................... 44
8.1 XML PROCESSING METHODOLOGIES ........................................................................... 45
8.1.1 SAX (Simple Access for XML)............................................................................ 45
8.1.2 DOM (Document Object Model)......................................................................... 49
8.1.3 Validating XML with an XSD using JAX-P ............................................................ 54
8.1.4 Difference between SAX and DOM ..................................................................... 55
9 JAX-B ................................................................................................................... 57
9.1 ARCHITECTURE .................................................................................................... 58
9.2 ONE-TIME OPERATION ........................................................................................... 62
9.2.1 How to use XJC or Schemagen? ........................................................................ 63
9.2.2 What does XJC generates? ............................................................................... 64
9.3 RUNTIME OPERATION ............................................................................................. 65
9.3.1 Un-Marshalling ............................................................................................... 65
9.3.2 Marshalling .................................................................................................... 70
9.3.3 In-Memory Validation ...................................................................................... 71
3
Mr. Sriman Web Services
4
Mr. Sriman Web Services
5
Mr. Sriman Web Services
6
Mr. Sriman Web Services
Web service
7
Mr. Sriman Web Services
1 Introduction
Web Service is the technology that allows us to build interoperable distributed
applications. Before understanding anything about web services let’s first of all try
to understand what is distributed application and what does interoperability means.
a) Increase the energy efficiency levels of the resource, in other words scale up
the hardware of the machine. Let’s say if the machine has been configured
with 2 GB RAM and takes 100 hours of time to compute the solution, increase
the RAM from 2 GB to 4 GB, so that the Job would be computed quicker within
95 hours. Increasing the RAM size from 2 GB to 4 GB has improved the
performance and reduced the processing time by 5 hours so, let’s say if I
increase the RAM from 4 to 8 or 8 to 16 or 16 to 32, the performance
improvement might be observed but it would not be always relatively
impacted. You might see performance improvement up to certain extent but
beyond that they may not be any further effect in performance even you scale
up the system.
b) Engineer the system. To build a solution for a job always there are multiple
ways of doing it, but to complete it within less amount of time we should have
a proficient skill set in working on it. When writing logic, we can produce the
same output by writing 10 lines of code and even with 5 lines of code, to
reduce the amount of code to build the solution; we need to engineer our
system. By modularization and effective design we can always reduce the
number of lines and tune the logic to complete it faster. The more you
engineer/tune the less the time required to process it. But this would also not
always relative, because even overdose of medicine will acts as poison, beyond
certain extent if you try to re-use or reduce the amount of lines, rather than
giving a positive effect; it might downgrade the performance of the application
itself.
By now we understood that we can reduce the turnaround time that is required to
execute a job by one person, but that is up to certain limit, may be could be 10%
or 20% of the actual time, but we may not surprisingly bring down it to half or
quarter of the original time by single person.
But there are use cases that demands high amount of throw put or less
processing time, such kind of jobs cannot be handled by one person rather we
need to distribute such jobs between more than one people. The same is shown in
the below figure.
8
Mr. Sriman Web Services
In the above diagram, it shows a 100 hours of job has been divided into multiple
parts (let’s say two equal 50 hours) and each part is independent with other part.
The parts are assigned or shared across two or more people, so that each one
would be able to execute on its own piece to build a partial solution, as there are
working parallel the time required to complete 100 hours of job by two person’s
working parallel is 50 hours and the time required to combine their individual
outputs to form the final output may be 5 hours. So, the total time required to
build the final solution would be 55 hours which when compare with one person
working on that job it’s a great performance improvement and drastic change in
turnaround time.
Initially we have programs which are designed to run on one Box/Machine. Like
when we develop “C” language program, it will execute on a machine and can talk
to other programs which are running on same machine. In this case if we run two
instances of the program “P1” on the same machine both instances will execute
simultaneously by sharing the totally hard of the same machine. In this case they
won’t be any performance improvement as they cannot scale up beyond the
current machine configuration.
9
Mr. Sriman Web Services
d) High utilization of resources: - There are some resources which are very
costly, let’s say printer. If want every employee in the organization to have
access to printer, instead of buying 100 printers for 100 employees, we can
have one printer which can shared across 100 employees so that it would be
utilized by everyone effectively.
1.2.1 CORBA
CORBA stands for Common Object Request Broker architecture. After socket
programming, the first API that has release by Java to support Distributed
10
Mr. Sriman Web Services
After writing the business logic, in order to expose the CORBA object over the
network it has to be deployed on MOM’s. MOM stands for Message Oriented
Middleware and is nothing but a CORBA server. The purpose of MOM is to host
and expose only the CORBA objects. But in order to use MOM, we need to
acquire license and involves cost (not open source).
Considering all the above factors, like development will starts with IDL (seems to
be different from general way of programming) and deploying requires a
licensing server, at those times working would CORBA seems to be complicated
and quite messy. This makes CORBA quickly vanish from the market.
1.2.2 RMI
RMI stands for Remote Method Invocation. After CORBA, SUN released RMI as
an API to support distributed programming. It allows a Java Object to be
exposed over the network. SUN designed RMI keeping in view of all the
complexities and drawbacks in CORBA and ensured those will not be re-
introduced in RMI. So, in RMI java developer instead of writing a different
language script like IDL, he will start with Java Object development and once he
finish writing the business logic in the POJO, he will give it as input to RMI
Compiler, which will generates abstractions (a layer on top of it) to expose over
the network.
Here the programmer need to worry to code a different language file or need not
write the code in some other generated object, rather the development starts
with POJO and once finishes will generate network abstractions to expose it.
With this if you observe almost all the dis-advantages with CORBA have been
fixed in RMI and it is light weight.
11
Mr. Sriman Web Services
1.2.3 EJB
EJB stands for Enterprise Java Bean, which is next to RMI. From the EJB’s
onwards the concept of managed object came into picture. You will write an
Object which acts as an EJB and is deployed on a managed server called EJB
container. While your EJB object is executing, it might need some external
infrastructural resource support, instead of programmer coding for it, like
security or transaction or auditing or connection pooling, these would be
configured, maintained and provided to the EJB object by EJB Container itself.
But the problem with EJB is when you expose an Object as EJB, it can be
accessed over the network by other programs. The other programs which wants
to access the EJB object should also be Java applications only and non-java
programs cannot access EJB’s as shown below.
12
Mr. Sriman Web Services
13
Mr. Sriman Web Services
2 Evolution
Initially every language can build programs which can run on one machine. There
after every program language strived to build applications which can not only talk
to the applications running on same machine but also they should be able to
communicate with programs running on different machines but, connected over the
network, which is nothing but distributed programming. With this the invention
didn’t end, they want to still find a way to build distributed programs which can talk
over heterogeneous systems (irrespective of platforms and programming
languages) is called interoperable distributed applications.
If vendor has their own stack of standards for example as shown below
Java programs can only understand the data transmitted over HTTP, so if a
Microsoft program is sending the data over FTP, it cannot be read/received by a
Java application.
In this case Interoperability never will become a reality. Finally it was realized by
every software vendor that we cannot build independently an interoperable
distributed applications, unless everyone has agreed upon same standards.
WS-I has released BP 1.0 (Basic Profile) specification document. The specification
document comprises of set of guidelines or standards that must be used to build an
interoperable distributed programs. BP 1.0 doesn’t talk about how to develop an
interoperable distributed application in Java rather they will talk about the
standards or guidelines to build web service in any programing language. After few
years of BP 1.0, WS-I has again released one more specification document BP 1.1
which is the successor of BP 1.0 which contains some advancements than its
earlier.
14
Mr. Sriman Web Services
To build WS-I’s BP 1.0 complaint Web Services SUN has released JAX-RPC API
and to build BP 1.1 complaint Web Services JAX-WS API has been released. As BP
1.1 is the successor of BP 1.0, similarly JAX-WS API is the successor of JAX-RPC
API.
Always using Specifications and API’s we cannot build programs rather for an API
we need implementation. There a lot of Implementations available for both JAX-
RPC API and JAX-WS API, few are open source and few other are commercial.
Below is the table showing the implementations of JAX-RPC API and JAX-WS API.
implementation to support
development of JAX-WS API
complaint Web services.
15
Mr. Sriman Web Services
3 Architecture
Let us try to understand what we need to build a Web Service in general. It’s
similar to block diagram of a computer like we need mouse, key board, monitor,
CPU etc. Let us also identify here what are all the various components required to
build a Web Service.
3.1 Medium
If two people want to exchange information between them, what they need? To
propagate their wave lengths from one person to other, they need medium.
Medium acts as a physical channel on which data would be exchanged. If two
computers want to exchange data, first they should be connected over a wire or
network.
3.2 Protocol
Having medium itself is enough? With medium we can propagate the wave
lengths, but there is not guarantee of receiving the information intact and
properly. Let’s say two people are talking to each other, instead of one person
listening to other both the people started talking to each other at the same time.
It seems instead of talking there are barking at each other, would the
communication be effective? Rather if there are set of rules that guards their
communication, for e.g.. first person says am starting the conversation so that
the other person would be in listening mode, once the first person finishes, he will
say am done so, that the other person can start the conversation by following the
same rules.
This indicates we need set of rules that guards the communication channel which
is nothing but a protocol. If two computer systems want to exchange data, having
network itself is not enough we need a protocol to guard the exchange of data
over them. Protocol simulates that everyone has their independent bands of
communication channel to exchange information, even though everyone is
sharing the same physical channel. In the same way if two programs want to
exchange the data over the network, they need physical data transport protocol
like TCP/IP or RMI/IIOP or HTTP or SMTP etc. The recommended protocol in case
of Web Service communication is HTTP.
16
Mr. Sriman Web Services
3.3 Language
Now we have medium and protocol to transmit information between two people,
but both the parties has to exchange the information in same language, which
means a common language to exchange information in an understandable manner
like English or French or Japanese etc.
If these two are computers, we can exchange the data between them in an ASCII
or UNICODE encoded characters. For example it could be a CSV or a text file of
information encoded in common encoding.
CSV files are good when your data is strictly tabular and you know its structure. If
you have relationships between different levels of data, CSV are not competent to
hold such information. CSV is not self-explanatory which means based on the
position of fields user has to interpret the type or nature of information. Let’s
consider a simple example to understand the same.
There are two systems, one is a Bank system and the other is client who is trying
to send the deposit data to deposit into his account. He has sent the information
in a CSV format as shown below.
The field order in which he sent the information is Serial No, Account No, Name,
Amount, Operation Type and Branch Code. The Bank system upon receiving the
data has started interpreting the data in this order Amount, Account No, Name,
Serial No, Branch Code and Operation Type.
The problem with the above representation is the data is not self-explanatory,
which is nothing but semantics of data is missing; the receiver of the data also
has to interpret the data in same order (which is not guarantee). This might lead
to incorrect operations as above instead of deposit, it leads to withdrawl.
Instead of CSV, we can represent the data in MS-Word, MS-Excel etc. But the
problem with these kinds of representations is those are recognized by only
Windows and few other platforms, which means those are platform dependent
formats. We are trying to build an interoperable solution, which means the data
we carry between systems must also be interoperable.
17
Mr. Sriman Web Services
<info>
<sno>1</sno>
<accno>AC324</accno>
<name>Suresh</name>
<amount>422</amount>
<operationType>D</operationType>
<branchCode>W</branchCode>
</info>
In the above XML it is clear that which data is conveying what type of information,
so that the receiver of this will not have a chance of miss-interpreting the
information. So, the defacto standard for exchanging information between
computers is XML.
<registration>
<accountNo>AC222</accountNo>
<password>533fd</password> Secret password
<username>John</username>
<password>33kk</password> Password with which want to register
</registration>
In the above XML we are trying to represent two different types of data one is
business data nothing but AccountNo, username and password with which you
want to register your account. The other one is helper data or processing data
secret password given by bank with which you can be authorized to register.
As discussed it contains two types of data, it would be confusing for the person
who is trying to read this XML, to identify which is processing data and which is
business data. We need a wrapper on top of it to differentiate the same, which is
nothing but SOAP.
SOAP stands for “Simple Object Access Protocol”. It is also an XML, but SOAP XML
has a rigid structure and has reserved grammar with which we need to write it.
SOAP XML has root element as Envelope and has two sections, first one is header
and second one is body as shown below.
18
Mr. Sriman Web Services
<Envelope>
<Header>
<!—processing data or helper data -->
</Header>
<Body>
<!—Business data -->
</Body>
</Envelope>
All the processing data will be placed under <Header> element and the business
data will be placed inside <Body> element. SOAP is also called as Binding
Protocol, because it binds our business XML. It acts as an Application Specific
Protocol, because the receiver of the SOAP XML will be able to identify and
differentiate which is processing data and which is business XML. SOAP defines
the rules in which other applications has to interpret the data so it is called
Application Specific protocol.
Along with that SOAP is also called as carrier of the actual Payload. As our
business XML is placed inside the SOAP XML and is carried by SOAP. It is also
called as carrier of the actual payload.
So, for a consumer in-order to get the data from the Provider, he needs to know
the information about the provider. This means the information about the
provider has to be document in some document like MS-Word or PDF etc. The
problem with this is you are trying to build an Interoperable distributed
application which can be accessible by any one literally, but the documentation
about it is being documented in non-interoperable document, will it be understood
by everyone. That means not only the program the documentation should also be
interoperable, there comes WSDL. WSDL Stands for Web Service Description
Language. It is also an XML type document, this makes it interoperable. WSDL
has a pre-defined structure and has grammar, using which you need to write the
WSDL document. WSDL document will provides the entire information about the
provider like Service name, Number of Operations, their parameters and return
types and Location of the Service etc.
The consumer can know the entire information about the provider by seeing its
WSDL document.
Note: - WSDL is a static entity which describes information about the Provider. It
is not a program to execute.
19
Mr. Sriman Web Services
b) Public UDDI – These are accessible globally across over the network. But few
would be open source hosting and few would be commercial.
From the above we understood what are the components required to build a Web
Service, below is the diagram depicting the Architecture of a Web Service.
Explanation: - Consumer is the person who tries to access the information from
the Provider, and Provider is the person who always services the Consumer.
20
Mr. Sriman Web Services
Those should be often referred to as Consumer and Provider and should not call
them as Client and Server in case of Web Services.
They need a common language to exchange data, the defacto standard for
exchanging information between computers is XML. But only XML is not enough,
as a Web Service communication not only transmits business data, it might also
transmit helper or processing information, so we need a layer on top of it called
SOAP.
SOAP stands for “Simple Object Access Protocol” acts as a binding protocol to
classify the information.
If the consumer wants to access the provider, he needs to know the information
about the provider. So, the information about the provider is documented in a
document called WSDL and is being published by the Provider in a registry called
UDDI. The process of putting the document into the UDDI registry is called
Publish and would be generally done by Provider.
Now the consumer has to connect to the registry and performs a search on the
registry which is called Discovery to find an appropriate WSDL document.
Downloads it locally and now starts understanding the information about provider.
He will builds a program called “Web Service Client” using the information in the
WSDL document through which he will sends the request and gets the response
back.
By the above we understood that language for exchanging the information is XML.
Binding protocol is SOAP which is nothing but XML and Description of the Service is
WSDL, is also XML. Registry in which we store the WSDL is UDDI, built on top of
XML technologies, everything in Web service is built on XML and without XML Web
Services would not be possible, so first we need to understand XML, let’s move to
XML.
21
Mr. Sriman Web Services
XML
22
Mr. Sriman Web Services
4 XML
XML stands for extensible markup language. Markup language is the language
using which you can build other languages like, HTML, XML.
XML is defined and governed by W3Org. The first and final version of XML is XML
1.0. XML is the document which represents data. Unlike C, C++, Java etc. XML is
not a programing language. It is the defacto standard for exchanging information
between computer systems. When we represent data in an xml document it would
be more structured and has well defined semantics attached to it. “Semantics” here
represents what a particular data field is representing or stands for, so that any
person reading the xml document would be able to interpret in the same manner.
Another significant feature of XML is, once written it is portable across the
platforms (Windows, Linux etc). No changes are required to carry the data across
platforms.
Every language has keywords. If you take example as C, it has keywords like (if,
for, while, do, break, continue etc.) but when it comes to XML there are no
keywords or reserved words. What you write will become the element of that XML
document.
As everything is written in terms of start and end elements, XML is said to be more
structured in nature. An XML Element may contain content or may contain other
elements under it. So, XML elements which contain other elements in it are called
as Compound elements or XML Containers.
Example:-
<book type=”entertainment”>
<isbn>isbn1001</isbn>
</book>
23
Mr. Sriman Web Services
In the above example “book” is an element which contains one attributes type
which acts as an supplementary information. Isbn is the sub-element of the book
element.
4.3 Well-formness
As how any programing language has syntax in writing its code, Well-formness of
XML document talks about how to write an XML document. Well-formness indicates
the readability nature of an XML document. In other way if an XML document is
said to be well-formed then it is readable in nature.
Following are the rules that describe the Well-formness of an XML Document.
1) Every XML document must start with PROLOG: - prolog stands for processing
instruction, and typically used for understanding about the version of XML used
and the data encoding used.
2) Root Element: - XML document must contain a root element, and should be the
only one root element. All the other elements should be the children of root
element.
3) Level constraint: - Every start element must have an end element and the level
at which you open a start element, the same level you need to close your end
element as well.
Example:-
If any XML is said to follow the above defined rules then it is termed as well-
formed.
24
Mr. Sriman Web Services
4.5 Validatity
Every XML in-order to parse (read) should be well-formed in nature. As said
earlier well-formness of an XML document indicates whether it is readable or not,
it doesn’t talks about whether the data contained in it is valid or not.
Validity of the XML document would be defined by the application which is going
to process your XML document. Let’s consider a scenario as follows.
You want to get driving license. In order to get a driving license you need to
follow certain process like filling the RTA forms and signing them and submitting
to the RTA department.
Instead of this can you write your own format of letter requesting the driving
license from an RTA department, which seems to be not relevant because driving
license is something that would be issued by the RTA department. So, the whole
and sole authority of defining what should a person has to provide data to get a
driving license will lies in the hands of RTA department rather than you.
In the same way when an application is going to process your xml document, the
authority of defining what should be there as part of that xml is lies in the hands
of the application which is going to process your document.
In the above xml even though it confirmes to all the well-formness rules, it cannot
be used for business transaction, as the 2nd <quantity> element carries the data
as “abc” which doesn’t makes any sense.
So, in order to check for data validity we need to define the validation criteria of
an XML document in either a DTD or XSD document.
25
Mr. Sriman Web Services
5 DTD
DTD stands for Document Type Definition. It is the document which defines the
structure of an XML document.
In an XML document we have two types of elements; elements which carry data
are called simple elements. An element which contains sub-elements under it is
called compound element.
In a language before using a variable we need to declare it. Similarly before using
an element in XML first we need to declare it in DTD. While declaring the element
in DTD, we need to tell whether it is a simple or compound element.
So, we need to understand the syntax of how to declare simple and compound
elements of an xml in dtd.
For e.g..
In an XML characters like “<”, “>”, ‘”’, “’” and “&” are valid characters and if the
text content contains those characters the parsers are going to parse or will expand
them as further entities.
For e.g..
In XML
<item>
<itemCode>IC200</itemCode>
<quantity>35</quantity>
</item>
26
Mr. Sriman Web Services
Let’s take a complete XML and derive how the DTD looks like for it.
1) Identify all the simple elements of XML from bottom of the XML and draft them
in the DTD.
2) Identify the compound elements of XML from lowest level in the XML and draft
them in the DTD.
XML Document
27
Mr. Sriman Web Services
? – Represents the sub element under a parent element can appear zero or one-
time (0/1).
+ - indicates the sub element must appear at least once and can repeat any
number of times (1 – N)
* - indicates the sub element is optional and can repeat any number of times
(0 - N)
You will mark the occurrence of an element under another element as follows.
Leaving any element without any symbol indicates it is mandatory and at max can
repeat only once.
In an e-mail body part we have content which can be mixture of any parsable
characters which can be declared as ANY type.
28
Mr. Sriman Web Services
<to>toaddr.com</to> <to>toaddr.com</to>
<from>fromaddr.com<from> <from>fromaddr.com<from>
<subject>mysub</subject> <mailBody>mysub</mailBody>
</mail> </mail>
As shown above to declare an attribute you need to use the tag ATTLIST and
elementname stands for which element you want to declare the attribute and
attributename stands for what is the attribute you want to have in that element.
Type Description
29
Mr. Sriman Web Services
Value Description
5.7.2 #REQUIRED
<!ATTLIST shippingAddress type CDATA #REQUIRED> this indicates type
attribute is mandatory in shipping address element.
5.7.3 #IMPLIED
<!ATTLIST shippingAddress type CDATA #IMPLIED>, this indicates the type
attribute in shippingAddress element is optional.
5.7.4 #FIXED
<!ATTLIST shippingAddress type CDATA #FIXED “permanent”>, this indicates the
type attribute in shippingAddress element must contain only the value as
permanent.
This indicates the type attribute in shippingAddress element should contain only
two possible values either permanent or temporary.
30
Mr. Sriman Web Services
Even though we can use DTD’s for defining the validity of an XML document, it is
not type safe and is not flexibile. XSD is more powerful and is type strict in nature.
XSD document is used for defining the structure of an XML document; it declares
elements and the type of data that elements carry.
As XSD is also an XML document so, it also starts with prolog and has one and only
one root element. In case of XSD document the root element is <schema>. All the
subsequent elements will be declared under this root element.
So, while writing an XSD documents we need to represent two types of elements
simple or compound elements. The syntax’s for representing a simple and
compound elements of XML in a XSD document are shown below.
<xs:complexType name=”typeName”>
<xs:sequence> or <xs:all>
<xs:element name=”..” type=”..”/>
<xs:element name=”..” type=”..”/>
<xs:element name=”..” type=”..”/>
</xs:sequence> or </xs:all>
</xs:complexType>
The same can be applied in case of complex type declaration in an XSD document.
In order to create user-defined data type in XSD document you need to declare a
complex type, creating a complex indicates you just declared the class structure.
Once you create your own data type, now you can define as many elements you
31
Mr. Sriman Web Services
need of that type. Let’s say for example I declared a complex type whose name is
AddressType as follows
<xs:complexType name=”AddressType”>
<xs:sequence>
<xs:element name=”addressLine1” type=”xs:string”/>
<xs:element name=”addressLine2” type=”xs:string”/>
<xs:element name=”city” type=”xs:string”/>
</xs:sequence>
</xs:complexType>
Now the above fragment indicates you created your own user-defined data type
whose name is “AddressType”. Now you can declare any number of elements
representing that type as shown below.
Let’s take an XML document for which we will show how its XSD looks like
<consignment>
<id>C4242</id>
<bookedby>durga</bookedby>
<deliveredTo>Sriman</deliveredTo>
<shippingAddress>
<addressLine1>S.R Nagar</addressLine1>
<addressLine2>Opp Chaitanya</addressLine2>
<city>Hyderabad</city>
<state>Andhra Pradesh</state>
<zip>353</zip>
<country>India</country>
</shippingAddress>
</consignment>
32
Mr. Sriman Web Services
<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”>
<xs:element name=”consignment” type=”consignmentType”/>
<xs:complexType name=”consignmentType”>
<xs:sequence>
<xs:element name=”id” type=”xs:string”/>
<xs:element name=”bookedby” type=”xs:string”/>
<xs:element name=”deliveredTo” type=”xs:string”/>
<xs:element name=”shippingAddress”
type=”shippingAddressType”/>
</xs:sequence>
</xs:complexType>
<xs:complexType name=”shippingAddressType”>
<xs:sequence>
<xs:element name=”addressLine1” type=”xs:string”>
<xs:element name=”addressLine2” type=”xs:string”>
<xs:element name=”city” type=”xs:string”>
<xs:element name=”state” type=”xs:string”>
<xs:element name=”zip” type=”xs:int”>
<xs:element name=”country” type=”xs:string”>
</xs:sequence>
</xs:complexType>
</xs:schema>
So while using the item element in the xml we need to declare the itemCode and
quantity sub-elements under item in the same order as shown below.
33
Mr. Sriman Web Services
<item>
<itemCode>IC303</itemCode>
<quantity>35</quantity>
</item>
When we use <xs:all>, under item element the itemCode and quantity may not
appear in the same order. First quantity might appear then itemCode can present
in the xml. When we use <xs:all> all the elements under it should appear atleast 0
and at max once.
<xs:complexType name=”USShippingAddressType”>
<xs:complexContent>
<xs:extension base=”shippingAddressType”>
<xs:sequence>
<xs:element name=”county” type=”xs:int”/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:simpleType name=”zipType”>
<xs:restriction base=”xs:int”>
<xs:totalDigits value=”4”/>
</xs:restriction>
</xs:simpleType>
34
Mr. Sriman Web Services
In case of attributes, we should declare the attributes in a complex type at the last
after the <xs:sequence> tag, because sequence doesn’t apply for attributes.
<xs:complexType name=”shippingAddressType”>
<xs:sequence>
<xs:element name=”addressLine1” type=”xs:string”/>
<xs:element name=”addressLine2” type=”xs:string”/>
<xs:element name=”city” type=”xs:string”/>
<xs:element name=”state” type=”xs:string”/>
<xs:element name=”zip” type=”xs:int”/>
<xs:element name=”country” type=”xs:string”/>
</xs:sequence>
<xs:attribute name=”type” type=”xs:string” use=”required”/>
</xs:complexType>
For the above element declaration the xml equivalent looks like below.
<zip zone=”local”>353</zip>
35
Mr. Sriman Web Services
It is not necessary to present both but either this or the other is mandatory in
impose such kind of constraint we need to use Choice element as shown below.
<xs:complexType name=”purchaseOrderType”>
<xs:sequence>
<xs:element name=”orderItems” type=”orderItemsType”/>
<xs:choice>
<xs:element name=”shippingAddress”
type=”shippingAddressType”/>
<xs:element name=”usShippingAddress”
type=”usShippingAddressType”/>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:schema….>
<xs:element name=”itemCode” type=”xs:string”/>
<xs:complexType name=”itemType”>
<xs:sequence>
<xs:element name=”itemCode” ref=”itemCode”/>
<xs:element name=”quantity” type=”xs:int”/>
</xs:sequence>
<xs:complexType>
</xs:schema>
36
Mr. Sriman Web Services
6.8.1 Import
Import has to be used when the namespaces of both the XSD documents are
different for e.g..
Po1.xsd
<xs:schema targetNamespace=”http://ebay1.in/sales/types”>
</xs:schema>
Po2.xsd
<xs:schema targetNamespace=”http://ebay2.in/sales/types”>
<xs:import namespace=”ttp://ebay1.in/sales/types”
location=”c:\po1.xsd”/>
</xs:schema>
If you observe in the above scenario po2.xsd want’s to use few elements
declared in po1.xsd. In order to do that first po2.xsd should refer the po1.xsd.
as both the namespaces of these documents are different we should use import
rather than include.
6.8.2 Include
Let’s say we have a XSD document with more than 100 elements. Writing or
managing the elements in one single XSD is not so easy and is error prone as
well. Instead we can split it in to two XSD’s and can include one into another.
Which means if two XSD’s are having the same namespace we need to use
include tag to include one in the other, which is similar to combining two into
one.
Po1.xsd
<xs:schema targetNamespace=”http://ebay1.in/sales/types”>
</xs:schema>
Po2.xsd
<xs:schema targetNamespace=”http://ebay1.in/sales/types”>
<xs:include schemaLocation=”po1.xsd”/>
<xs:schema>
37
Mr. Sriman Web Services
7 XSD Namespace
Every programming language one or in another way allows you to declare user-
defined data types. Let’s consider the case of “C” language it allows you to declare
your own types using Structure. In case of “C++” Class declaration allows you to
declare your own type, same in case of Java as well.
When it comes to XSD you can declare your element type using XSD complex type
declaration.
As how any language allows you to create your own types, they allow you to
resolve the naming collision between their types. Let’s consider the case of Java; it
allows you to declare your own types by class declarations. But when a
programmer is given a choice of declaring their own types, language has to provide
a means to resolve type names collision declared by several programmers. Java
allows resolving those type naming conflicts using packages.
Packages are the means of grouping together the related types. It will allow you to
uniquely identify a type by prefixing the package name. In the same way XSD also
allows you to declare your own data type by using Complex Type declaration and in
the same way it allows you to resolve the type naming conflicts by means of
Namespace declaration.
2) Using the elements that are declared under a namespace in xml document.
38
Mr. Sriman Web Services
Example:-
<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”
targetnamespace=”http://durgasoft.com/training/calendar/types”>
<xs:complexType name=”courseType”>
<xs:element name=”courseId” type=”xs:string”/>
<xs:element name=”courseName” type=”xs:string”/>
<xs:element name=”duration” type=”xs:datetime”/>
</xs:complexType>
</xs:schema>
So, while creating an element “course” of type courseType you should use the
qName of the courseType rather simple name. (qName means
namespace:element/type name).
But the namespace labels could be any of the characters in length, so if we prefix
the entire namespace label to element/type names it would become tough to
read. So, to avoid this problem XSD has introduced a concept called short name.
Instead of referring to namespace labels you can define a short name for that
namespace label using xmlns declaration at the <schema> level and you can use
the short name as prefix instead of the complete namespace label as shown
below.
<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”
targetnamespace=http://durgasoft.com/training/calendar/types
xmlns:dt=”http://durgasoft.com/training/calendar/types”>
<xs:element name=”course” type=”dt:courseType”/>
<xs:complexType name=”courseType”>
<xs:element name=”courseId” type=”xs:string”/>
<xs:element name=”courseName” type=”xs:string”/>
<xs:element name=”duration” type=”xs:datetime”/>
</xs:complexType>
</xs:schema>
In java we can have only one package declaration at a class level. In the same
way we can have only one targetNamespace declaration at an XSD document.
39
Mr. Sriman Web Services
<course xsi:schemaLocation=”http://durgasoft.com/training/calendar/types
file:///c:\folder1\folder2\courseInfo.xsd”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-Instance”>
</course>
In the above xml we stated this xml is using xsd document courseInfo.xsd whose
namespace is http://durgasoft.com/training/calendar/types
If you want to include two XSD documents in the xml then you need to declare in
schemaLocation tag <namespace1> <schemalocation1> <namespace2>
<schemalocation2>.
For example:-
<course xsi:schemaLocation=”http://durgasoft.com/training/calendar/types
file:///c:\folder1\folder2\courseInfo.xsd
http://durgasoft.com/training/vacation/types
file:///c:\folder1\folder2\vacation.xsd”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-Instance”>
</course>
Now in the above xml we are using two XSD documents courseInfo.xsd and
vacation.xsd. With this declaration we will not be able to find whether the course
element is used from courseInfo.xsd or vacation.xsd. To indicate it we should
prefix the namespace to the course element.
But the namespace labels can be arbitrary string of characters in any length. So,
we need to define short name, so that we can prefix shortname while referring
the elements as shown below.
<dc:course xsi:schemaLocation=”http://durgasoft.com/training/calendar/types
file:///c:\folder1\folder2\courseInfo.xsd
http://durgasoft.com/training/vacation/types
file:///c:\folder1\folder2\vacation.xsd”
xmlns:xsi=http://www.w3.org/2001/XMLSchema-Instance
xmlns:dc=”http://durgasoft.com/training/calendar/types”>
</dc:course>
40
Mr. Sriman Web Services
Po1.xsd
Po2.xsd
Po.xml
41
Mr. Sriman Web Services
• DTD stands for document type • XSD stands for XML Schema
definition Documents
• DTD’s are not XML Type documents • XSD’s are XML Type documents
• DTD’s are tough to learn as those are • As XSD’s are XML type documents it is
not XML documents. So, an XML easy for any programmer to work with
programmer has to under new XSD.
syntaxes in coding DTD
• XSD’s are strictly typed, where the
• DTD’s are not type safe, these will language has list of pre-defined data
represents all the elements with data types in it. While declaring the element
type as (#PCDATA). you need tell whether this element is of
what type.
• DTD’s don’t allow you to create use-
defined types. • XSD’s allows you to create user-
defined data types using complexType
declaration and using that type you can
create any number of elements.
42
Mr. Sriman Web Services
JAX-P
43
Mr. Sriman Web Services
8 JAX-P
JAX-P stands for Java API for XML Processing. As we discussed earlier, XML is also
a document which holds data in an XML format. Initially in Java there is no API that
allows reading the contents of an XML document in an XML format. Java
programmers has to live with Java IO programming to read them in a text nature
or need to build their own logic to read them in XML format.
By looking at this lot of Java software vendors in the market has started building
their own libraries/API’s that allows processing an XML documents in XML nature.
Few of them are DOM4J, JDOM.
But the problem with third party libraries are you need to stick with vendor specific
classes, as there is no common API which facilities switching between them.
Advantage of using standard JDBC API is your API classes never allow your code to
expose to the implementation, so that your code would be flexible enough to
change between different databases by simply switching the drivers.
Let’s say in order to execute a sql query against a database you need Connection.
But Connection is an Interface provided by JDBC API, and we need to find the
implementation class of Connection Interface and should instantiate it. Instead of
us finding the Implementation class, JDBC API has provided a class DriverManager
which acts as a factory class who knows how to find the appropriate
implementation of Connection Interface and instantiate it.
44
Mr. Sriman Web Services
After many software vendors started developing their own libraries, sun has finally
released JAX-P API which allows us to work with XML documents. As indicated
JAX-P is an API which means not complete in nature, so we need implementations
of JAX-P API and there are many implementations of JAX-P API available for e.g..
Crimson, Xerces2, Oracle V2 Parser etc.
Xerces2 is the default parser that would be shipped as part of JDK1.5+. This
indicates if you are working on JDK1.5+ you don’t need any separate Jar’s to work
with JAX-P API.
SAX and DOM are the universal methodologies of processing (reading) XML
documents irrespective of a particular technology. Few programming
languages/API’s supports only SAX way of reading documents, few other supports
only DOM and quite a few number support both the ways of reading.
Let us try to understand what these methodologies are and how to read XML
documents following these methodologies.
Source: - is the originator of event, who can raise several types of events.
Events could be of multiple types if we consider AWT, we can consider source as
a button, which is capable of raising several types of events like button click,
mouse move, key pressed etc.
Listener: - Listener is the person who will listens for an event from the source.
Listener listens for a specific type of event from the source and triggers an even
handling method on the Event handler to process it.
45
Mr. Sriman Web Services
So here source is the XML document which can raise several types of events
based on the type of element it is pointing to (e.g... START_DOCUMENT,
START_ELEMENT etc...). Listener is the parser who will reads the XML document
and triggers a method call on the Handler. Event handler contains several
methods to handle various types of events as shown below.
SAX is very fast in processing XML documents when compared with DOM and
consumes less amount of memory, as at any given point of time it loads only
one element into the memory and process. Here one key thing to note is using
SAX we can only read the XML document, we cannot modify/create a document.
Using JAX-P API we can process XML documents in SAX model, here also source
is the XML document, who is capable of raising multiple types of events likes
startDocument, startElement, endDocument etc. In order to read the elements
of XML and process them by raising events, we need a parser and here in SAX it
is SAXParser.
Along with the parser, we need a Handler class to handle the event and process
it. A handler class would be written by extending it from DefaultHandler, we can
override the methods to process respective events. Below is the example
showing a class extending from DefaultHandler.
46
Mr. Sriman Web Services
package com.saxparser.handler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
@Override
public void endDocument() throws SAXException {
System.out.println("END DOCUMENT");
}
@Override
public void endElement(String arg0, String arg1, String localName)
throws SAXException {
System.out.println("</"+localName+">");
}
@Override
public void startDocument() throws SAXException {
System.out.println("START DOCUMENT");
}
@Override
public void startElement(String arg0, String arg1, String localName,
Attributes arg3) throws SAXException {
System.out.print("<"+localName+">");
}
}
In the above class we are overriding five methods which would be triggered
based on the type of elements the parser is pointing to on the source XML
document.
a) startDocument – would be triggered at the start of the XML document
b) startElement – Whenever the parser encounters the starting element, it
raises this method call by passing the entire element information to the
method.
c) characters – This method would be invoked by the parser, whenever it
encounters data portion between the XML elements. To this method it passes
the entire XML as character array along with two other integers one
indicating the position in the array from which the current data portion begins
and the second integer representing the number of characters the data span
to.
d) endElement – would be triggered by the parser, when it encounters a closing
element or ending element.
47
Mr. Sriman Web Services
Once the handler has been created, we need to call the parser class parse()
method by passing the source as XML and the handler as the object of handler
class which we created just now. So, that the parser will reads the XML elements
and triggers a respective method call on the handler object provided.
The below program will reads the XML document sequentially and prints it on to
the console.
package com.saxparser.parser;
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
import com.saxparser.handler.POHandler;
48
Mr. Sriman Web Services
49
Mr. Sriman Web Services
Hierarchical
Model
The above diagram shows for an Input XML how DOM loads and builds a tree
structure representing elements and data.
As DOM loads the entire XML into memory at one shot, to load it takes some
time and as it holds the complete XML in-memory, it consumes more amount of
memory. That’s the reason DOM is relatively slow when compared with SAX. The
main advantage of DOM is unlike SAX, it is a read/write API which allows you to
create/modify a document.
Anything in DOM is called a Node. There are several types of Node like
Document Node, Element Node, Text Node and Empty node etc. The top of the
document is called the Document Node, if an element which is enclosed in
angular braces (<>) then it is called element node and if it just represents data
then it is called Text node.
When we give XML document to DOM, it loads the XML and builds tree structure
representing elements as nodes as described above. Then it places a pointer to
the top level of the tree which is a Document Node.
50
Mr. Sriman Web Services
• a – is parent
• b – is child of parent a
• a – is parent
As explained above except the root element all the other elements have a parent
node. Children of same parent are called brother/sister in other words siblings.
JAX-P provides a way to work with these nodes in Java, JAX-P has provided
methods like getFirstChild(), getChildNodes etc to access children of a parent. In
the same way to access the siblings it has provided methods like
getNextSiblings().
Before using the above methods, first of all we need to load the XML document
as described earlier. An XML document in JAX-P DOM is represented in
Document class object. As said earlier JAX-P is an API and
org.w2c.dom.Document is an interface. So, we need to provide implementation
for Document object and should instantiate by loading the XML into it.
So, we need a Builder which will read the existing XML, loads and places in the
Document object, this would be done by DocumentBuilder, he is the person who
knows how to read an existing XML document and loads in memory, along with
that using DocumentBuilder we can create or modify existing documents as well
(DOM is a read/write API so to support writing we need builder to build/modify
document).
51
Mr. Sriman Web Services
After creating the Document object, it points to the top of the Document which is
called Document Node. Now we need to use methods to navigate between the
elements of it.
package com.domparser.parser;
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
System.out.println(poDocument.getFirstChild().getFirstChild().getNodeNa
me());
}
}
52
Mr. Sriman Web Services
Instead to print the entire XML document on to the console we need to traverse
all the elements recursively. As you know DOM loads the XML document
represents it in a Hierarchical fashion (Tree structure), any Hierarchical
representations needs recursion technic as the things would be in parent and
child nested format. If we take Binary tree, the tree traversal algorithms are In-
order, pre-order and post-order which are recursive technic based traversal
algorithms.
The below programs shows how to traverse between all the DOM nodes
recursively.
package com.po.parser;
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
//System.out.println(doc.getFirstChild().getFirstChild().getNodeName());
printNode(doc);
}
Contd…..
53
Mr. Sriman Web Services
To validate an XML we need either a DTD/XSD. Now we are trying to understand how
to validate an XML with an XSD in java using JAX-P API.
To validate an XML first of all we need to load the contents of XSD and keep in a java
object called Schema. Schema is coming from JAX-P API which means it is an abstract
class. The implementation for the Abstract class Schema will be there with resp
implementation, in our case with Xerces2.
As we don’t know who is the implementation for Schema class we need one more
factory class called SchemaFactory. While creating the SchemaFactory we need to
pass the input as W3C XML Schema Namespace URI as input, to indicate we are going
to read the contents of XML Schema compliant XSD.
54
Mr. Sriman Web Services
After creating the Schema object call a method newValidator() will gives you the
validator object. On this object you can call the method called validate by passing XML
as input.
If the XML passed is invalid, it throws exception otherwise will not return anything.
SchemaFactory schemaFactory =
SchemaFactory.newInstance(XMLConstants.W3C_XML_NS_URI);
Validator v = poSchema.newValidator();
SAX DOM
• SAX stands for Simple Access for • DOM stands for Document Object
XML API Model.
• It is an event based processing • It is a hierarchical processing model,
model where it loads the entire XML in
• It process the XML sequentially one memory and represents in tree
after the other from top to bottom structure.
• It consumes less amount of • DOM supports random access of
memory as at any point of time elements.
loads only one element into the • It consumes huge amount of
memory memory as it loads the entire XML
• It is faster when compared with and forms tree structure (Generally
DOM as it doesn’t need to load or for 1kb of xml document it takes
form anything. 10kb memory to hold in memory,
• SAX is an readonly API, which which means it multiplies by 10X)
means we can just read the XML • It is slow when compared with SAX
documents, but we cannot modify as it has to represent the XML by
or create new. loading it.
• DOM is a read and write API using
which we can read/modify/create an
XML document.
In order to overcome the both the dis-advantages in SAX and DOM new
processing model came which is STAX, stands for Streaming API for XML. This is
unlike SAX event based or DOM hierarchical based, it is a pull based event
parser.
55
Mr. Sriman Web Services
JAX-B
56
Mr. Sriman Web Services
9 JAX-B
JAX-B stands for Java Architecture for XML Binding; it is the API that is used for
Binding Java Object to XML document and XML documents to Java Object back.
Let us try to understand, where we can use JAX-B in a typical Web service
communication. As we know in Web service communication always they involve
two actors Consumer and Provider. Consumer could be written in any language and
even the Provider can also be coded in any language.
If we consider a scenario where consumer and provider both are coded in Java
Language and now the consumer wants to send some information to the provider.
As consumer is a java program he holds the information in-terms of Java Object,
so in order to send the Java Object data over the network, he needs to serialize the
contents of that object into bits and bytes and has to send to Provider. Up on
receiving the serialized stream of data, the Provider will de-serialize and build back
the object for processing. The problem with this approach is Serialization is the
protocol proprietary for Java language and non-Java programs cannot understand
serialized data send by java application. So, this breaks the thumb rule
Interoperability.
So, if the consumer wants to send some information to the provider rather than
converting it into serialized stream of data, he should convert the Java Object data
to XML representation and should send to Provider. Now provider upon receiving
the XML he has to convert it to Java Object and process it. Again Provider instead
of returning Java Object as response, he should convert the response Object to
XML and should send it to consumer as response. The consumer has to convert
that incoming XML data to Object to use it. This is depicted in the below diagram.
By now we understood we should not use Object serialization for exchanging data
in web services rather we should convert them to XML. In-order to work with XML
java has already provided API’s for dealing with XML data which is JAX-P. In JAX-P
we can use either SAX or DOM parser to convert Java to XML and wise versa.
57
Mr. Sriman Web Services
Even though we can achieve this with JAX-P, a programmer has to write manually
the parser’s dealing with this, and more over there are limitations with JAX-P.
Let’s say if a Java Program wants to modify a Purchase Order XML document data,
it contains several things like OrderItems, Items and ShippingAddress information.
Rather than dealing them as elements, attributes or Text node, it would be easy for
a Java Programmer to look at them in-terms of Java Objects with data and modify
them than modifying them as XML. This can be accomplished by using the XML
Binding API’s.
Initially Java doesn’t have XML Binding supported API’s; there are lot of third party
XML binding libraries are released by software vendors in Java like JibX, Castor,
XML Beans, Apache Data binding API, Javolution etc. Then SUN has realized and
released its own API for dealing with XML Binding in Java “JAX-B API”. SUN has
even released an implementations for it JAX-B RI (Reference Implementation)
along with that we have one open source implementations for JAX-B API, JaxMe.
Basically XML Binding API’s are categorized into two types of tools.
a) Design Time tools – In these type of tools, there will be an Binding compiler
which will take a Schema or DTD as input and generated supported classes for
converting the XML to Object and Object to XML
b) Runtime tools – These will not generate any classes rather on fly will take the
XML as an input and based the elements names, matches them with
corresponding attribute names of the class and will convert XML into Object of
the class.
When it comes to JAX-B API it is a design time tool, where it will come up with its
own compiler to generated classes to support the binding process. Before
proceeding further on JAX-B let us first try to understand its architecture and its
offerings.
9.1 Architecture
Most of the XML Binding API’s architectures are similar to, what we are discussing
now.
If a Java Object is following the structure of a Java class then that Object is called
Instance of that class. If XML document is following the structure of an XSD
document can I call the XML as an Instance of that XSD or not? Certainly the
answer for this would be yes.
58
Mr. Sriman Web Services
If we try to derive a logical conclusion from the above, we can understand that
Classes and XSD documents both try to represent the structure, so we can create
set of Java classes which represents the structure of an XSD document, then the
XML document (holds data) representing the structure of that XSD can be
converted into its associated Java class Objects. Even the wise versa would also be
possible.
Let us try to deep down into the above point. How to created user defined data
type in Java? Using class declaration. How to created user defined data type in
XSD? By using ComplexType declaration. Which means a ComplexType in XSD is
equal to a Java class in Java. As XSD document means it contains elements and
multiple ComplexType’s so, to represent the structure of an XSD document in Java,
it is nothing but composition of various Java classes (one Java class one XSD
ComplexType) representing its structure.
59
Mr. Sriman Web Services
In the above XSD we have one element and four ComplexType declarations, as we
discussed earlier ComplexType declarations in XSD are equal to a Java class in
Java. So from the above we can derive four Java classes as shown below.
60
Mr. Sriman Web Services
From the above we can create the PurchaseOrderType object representing the root
element of XSD, can I hold the PurchaseOrder XML document data into this
instance or not? Absolutely the answer would be yes, because PurchaseOrderType
is representing the structure of the XSD document, so its instance can hold its XML
data.
With this we understood that we can created the Java classes representing the
structure of an XSD document, hence those classes are called as Binding Classes as
those are bonded to the XSD document structure and the objects out of those
classes are called binding objects.
Now we know that we can convert the XML document data into a Binding Class
Object, so the process of converting an XML to a Binding class Object is called Un-
Marshalling. And the process of converting a Binding Object back into XML
representation is called Marshalling and both the types of operations are supported
by any of the XML Binding API’s including JAX-B.
The above architecture is the generalized architecture which can be applied to any
XML Binding API’s including JAX-B.
61
Mr. Sriman Web Services
With our earlier discussions we understood that a typical XML Binding API should
support Un-Marshalling and Marshalling operations. But to perform Un-Marshalling
and Marshalling Operations do we need binding classes or not?
Let’s say I want to convert the Purchase Order XML document to Object, this is
Un-Marshalling. To perform Un-Marshalling do we need Binding classes
representing the structure of the Purchase Order XSD or not? So the programmer
has to read the contents of the XSD and based on the number of complex types
he needs to create equivalent Java classes representing their structure. As our
purchase order XSD document contains only four complex types it would be easy
for the developer to determine the relations between the classes and can create.
Let’s say I have an XSD document in which 100 ComplexType declarations are
there, is it easy for a developer to develop 100 Java classes representing the
structure of 100 ComplexTypes. Even though it seems to be feasible, but it is a
time taking task.
So, instead of writing the Binding classes manually, JAX-B has provided a tool to
generated Binding classes from XSD called XJC. And to generate XSD from a
Binding class there is another tool called Schemagen.
If I have an XSD document, how many times do I need to generate Java classes
to hold the data of its XML? It would be only once, because classes will not hold
data they just represents structure, so instances of those classes holds data of an
XML. Even the reverse would also be same. As we need to generate the Binding
classes or XSD only once this process is called one-time operations. And there are
two types of one-time operations.
a) XJC – XSD to Java compiler – Generates Binding classes from XSD document
Point to recollect: - We said JAX-B is a design time tool, if you see now it has a
binding compiler which will generates classes at design time.
62
Mr. Sriman Web Services
C:\Sun\JWSDP-2.0
|-- JAXB
| -- lib
| -- bin
| -- xjc.bat, xjc.sh, schemagen.bat and schemagen.sh
XJC compiler will take input as XSD and will generates set of binding classes. Now
where should I generate these binding classes, do I need to generate them in the
JAXB\bin directory or by Project Folder “src” directory? The answer would be
should generated in your project source directory. So to generate under source
directory of your project you need to run the XJC.bat from the Project directory
rather that the JAXB\bin directory. To run it from project directory we need to set
the system path pointing to it as shown below.
After setting the path, we need to switch to the project directory. For example if
your project is under D:\ drive and the folder is Sample you need to switch to the
Sample directory under D:\ drive and should execute the XJC.bat by giving XML
as input as shown below.
C:> cd D:\Sample
Xjc –d src resources\po.xsd
In the above command we are saying take the po.xsd as an input under resources
directory (from the current directory) and generate the binding classes under (-d
represents the directory) src directory in my Sample Project.
63
Mr. Sriman Web Services
All the binding classes would be generated into the above package
64
Mr. Sriman Web Services
So, by the above we understood that not every Java class is called as Binding
class, only the classes which are annotated with JAX-B annotations are called
binging classes.
So from the above binding classes we can even generated XSD document by
running the Schemagen tool as well, this is left to you as exercise.
b) Marshalling – The process of converting Java Object with data to its XML
equivalent
9.3.1 Un-Marshalling
As described earlier, the process of converting an XML document into Java
Object is called Un-Marshalling. In order to perform Un-Marshalling, you need to
have Binding Classes with you. You can generate these by running XJC compiler.
If you run XJC compiler on the po.xsd which was described earlier, the following
binding classes will be generated shown below.
65
Mr. Sriman Web Services
package org.amazon.types.sales;
@XmlAccessorType(AccessType.FIELD)
@XmlType(name = "shippingAddressType", propOrder = {
"addressLine1",
"addressLine2",
"city",
"state",
"zip",
"country"
})
public class ShippingAddressType {
@XmlElement(namespace = "http://amazon.org/types/sales")
protected String addressLine1;
@XmlElement(namespace = "http://amazon.org/types/sales")
protected String addressLine2;
@XmlElement(namespace = "http://amazon.org/types/sales")
protected String city;
@XmlElement(namespace = "http://amazon.org/types/sales")
protected String state;
@XmlElement(namespace = "http://amazon.org/types/sales", type =
Integer.class)
protected int zip;
@XmlElement(namespace = "http://amazon.org/types/sales")
protected String country;
package org.amazon.types.sales;
@XmlAccessorType(AccessType.FIELD)
@XmlType(name = "itemType", propOrder = {
"itemCode",
"quantity"
})
public class ItemType {
@XmlElement(namespace = "http://amazon.org/types/sales")
protected String itemCode;
@XmlElement(namespace = "http://amazon.org/types/sales", type =
Integer.class)
protected int quantity;
package org.amazon.types.sales;
@XmlAccessorType(AccessType.FIELD)
66
Mr. Sriman Web Services
@XmlElement(namespace = "http://amazon.org/types/sales")
protected List<ItemType> item;
package org.amazon.types.sales;
@XmlRootElement
@XmlAccessorType(AccessType.FIELD)
@XmlType(name = "purchaseOrderType", propOrder = {
"orderItems",
"shippingAddress"
})
public class PurchaseOrderType {
@XmlElement(namespace = "http://amazon.org/types/sales")
protected OrderItemsType orderItems;
@XmlElement(namespace = "http://amazon.org/types/sales")
protected ShippingAddressType shippingAddress;
Package-Info.java
@javax.xml.bind.annotation.XmlSchema(namespace =
"http://amazon.org/types/sales")
package org.amazon.types.sales;
67
Mr. Sriman Web Services
package org.amazon.types.sales;
@XmlRegistry
public class ObjectFactory {
public ObjectFactory() {
}
public ShippingAddressType createShippingAddressType() {
return new ShippingAddressType();
}
public OrderItemsType createOrderItemsType() {
return new OrderItemsType();
}
public PurchaseOrderType createPurchaseOrderType() {
return new PurchaseOrderType();
}
@XmlElementDecl(namespace = "http://amazon.org/types/sales",
name = "purchaseOrder")
public JAXBElement<PurchaseOrderType>
createPurchaseOrder(PurchaseOrderType value) {
return new
JAXBElement<PurchaseOrderType>(_PurchaseOrder_QNAME,
PurchaseOrderType.class, null, value);
}
Having the binding classes will not automatically converts the XML document
into Object of these classes, rather we need a mediator who would be able to
read the contents of the XML, and identify the respective binding class for that
and creates objects to populate data. This will be done by a class called
“Unmarshaller”. As JAX-B is an API, so Unmarshaller is an interface defined by
JAX-B API and its JAX-B API implementations (JAX-B RI or JaxMe) contains the
implementation class for this interface.
The object of Unmarshaller has a method unmarshal() , this method takes the
input as XML document and first check for Well-formness. Once the document is
well-formed, its reads the elements of the XML and tries to identify the binding
classes for those respective elements based on @XMLType and @XMLElement
annotations and converts them into the Objects.
68
Mr. Sriman Web Services
2) Where does un-marshaller should search for identifying a binding class (is it
in entire JVM memory or classpath?)
While creating the JAXBContext, we need to supply any of the three inputs
stated below.
With the above statement, the JAXBContext would be created and loads the
classes that are specified in the package or referred by ObjectFactory or the
individual binding classes specified and creates a in-memory context holding
these.
69
Mr. Sriman Web Services
package com.po.unmarshall;
System.out.println(poType.getShippingAddress().getAddressLine1());
System.out.println(poType.getOrderItems().getItem().get(0)
.getItemCode());
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
9.3.2 Marshalling
Marshalling is the process of converting the Object data to XML. For performing
Marshalling also we need to first of all have the Binding classes. Once we have
the Binding classes, we need to create the Object of these classes and should
populate data in them.
These objects can be marshaled to XML using the Marshaller. Again Marshaller is
an interface, to instantiate it we need JAXBContext. Then we need to call a
method marshall by giving input as XML and Outputstream where we want to
generate the output to. The below program depicts the same.
70
Mr. Sriman Web Services
package com.po.unmarshall;
poMarshaller.marshal(pot, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
An XML can be validated against an XSD document, so we need to read the XSD
document and should represent it in a Java Object called Schema.
71
Mr. Sriman Web Services
But Schema is an interface and to create the Object of interface, we need factory
called SchemaFactory. But schema factory can created various types of XSD
documents, so we need to provide the grammar of XSD document which you
want to load or created and would be done as show below.
SchemaFactory sFactory =
SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_URI);
Now we need to load the XSD document into the Schema class object as shown
below.
Once the schema object is created holding the structure of XSD, we need to give
it to Unmarshaller before calling the unmarshal(). So, that Unmarshaller will
validate the input XML with this supplied Schema Object and then performs
Unmarshalling. Otherwise Unmarshaller will throw exception, indicating the type
of validation failure. The below programs shows how to perform in-memory
validation.
package com.po.unmarshall;
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema poSchema = sFactory
.newSchema(new File("po.xsd"));
System.out.println(poType.getShippingAddress().getAddressLine1());
System.out.println(poType.getOrderItems().getItem().get(0)
.getItemCode());
}
}
72
Mr. Sriman Web Services
73
Mr. Sriman Web Services
JAX-RPC
74
Mr. Sriman Web Services
Now in a typical Web Service communication, the consumer will sends the initial
request with some data to the Provider. The consumer cannot send Object data
over the network; rather he needs to convert it into XML and needs to place the
XML into SOAP XML. Then the SOAP XML is being transported over the HTTP
protocol. This means the consumer will send a HTTP request, in order to receive
the HTTP request being sent by the consumer, at the Provider end we need to
75
Mr. Sriman Web Services
have a HTTP Listener. The listener will listens for the incoming request and
forwards it for further processing as shown below
There are two types of Endpoints, where a developer can choose while
developing a Provider.
Most of the people prefer to use Servlet endpoint rather than EJB endpoint as
EJB seems to be heavy and costly component, and for the sake of developing
Web services, the application needs to be hosted on an EJB container.
76
Mr. Sriman Web Services
In this case also the Consumer program would be blocked on the Providers
method call (request) and will not proceeds execution until the Provider returns
response. Which means the Consumer opened HTTP Connection would be open
till the Provider returns response.
For e.g. let us consider an example like you are sending a letter to your friend,
when you post the letter it would be carried by the postmaster to your friend.
Once the letter has been received, your friend may not immediately read the
letter, rather when he finds leisure he will read. Till your friend reads the letter
and give the reply the postmaster can’t wait at your friends door rather he
moves on. Now when your friend reads your letter, then he will reply to your
letter by identifying the from address on the letter and post back’s you the reply.
As the response here is not immediate and is being sent after sometime, this is
also called as Delayed response pattern.
77
Mr. Sriman Web Services
For e.g. a lecturer is dictating the notes, every student has their own way of
writing the notes. Someone may right the notes from bottom to top, others
might right from top to bottom.
In the same way, in order to send information, the consumer has to prepare his
data in XML format. How does consumer represents the data in the XML
document is called Message Exchange format.
The message exchange format would be derived by two parts 1) Style and other
is 2) Use.
a) Style – The possible values the Style part can carry is rpc and document
78
Mr. Sriman Web Services
By default any JAX-RPC API based web service uses the default message exchange
pattern as RPC-Encoded.
Before developing a consumer, first they should be a provider to access it. So, let
us start first with Provider Development. As you know there are multiple things you
need to consider while building provider, we are developing here JAX-RPC SI –
Contract Last – Servlet Endpoint – Sync req/repl – RPC-Encoded Service.
As we are Java programmers, it would be easy for us to start with Java rather
than with WSDL, so we are trying to understand development of the provider
using Contract Last.
Let us try to under step by step, how to develop a JAX-RPC SI service in contract
last approach.
a) Write SEI Interface – Always from an architecture point of view, the contract
between the consumer and the provider is WSDL. From Java point of view, the
contract between consumer and the provider is Interface. How does the
consumer knows the number of operations exposed by the provider,
declaratively he can see it in WSDL and from program perspective he can refer
the Interface.
The Web service development always starts with SEI interface, stands for
Service Endpoint Interface. As it describes the entire information about the
Provider (service), it is called Service Endpoint Interface. It acts as a contract
between Consumer and Provider. All the methods declared in the SEI interface
are exposed as Web Service methods. There are certain rules you need to
follow while writing SEI interface in JAX-RPC API described below.
79
Mr. Sriman Web Services
ii) Declare all the methods which you want to expose as Remote methods –
If you want to expose five methods as Web service methods, all those
five methods has to be declared in SEI interface. Only the methods
declared in SEI interface are exposed as Web Service methods or
remote accessible methods, others would be treated as local methods.
iii) Web Service methods should take parameters and return returnvalues as
Serializable – The methods we declare in SEI interface should take
parameters as Serializable, and even return values must be serializable.
class BookInfoRetreiver {
public void findBook(int isbn) {
try{
BookInfo info = // call service and get Book info
// perform something using bookInfo
} catch(RemoteException re) {
} catch(NullPointerException npe){
}
}
}
Now in the above code, we are trying to get the book information by
calling the service, after getting the BookInfo, we are computing
something with the data. While executing the findBook method an
exception was occurred, how do I need to find whether the exception
was caused due to Web service call or the local code has thrown the
error? If the type of Exception being caught is RemoteException, it
indicates a Remote program has caused the error. Otherwise would be
considering as local code has raised the exception.
80
Mr. Sriman Web Services
With the above rules, let us try to write an SEI Interface as shown below.
package com.store.service;
import java.rmi.Remote;
import java.rmi.RemoteException;
// SEI
public interface Store extends Remote {
float getBookPrice(String isbn) throws RemoteException;
}
The implementation class methods will contain business logic to handle and
process the incoming requests, but the logic you wrote here may or may not
raise any exceptions. In a case where your logic is causing any exceptions, you
don’t need to declare your method to throw RemoteException.
Below snippet shows the Implementation class for the above SEI interface.
81
Mr. Sriman Web Services
package com.store.service;
import java.rmi.RemoteException;
The wscompile tool is shipped as part of JWSDP. For developing a JAX-RPC API
RI based Web service we need some set of tools/compilers to generate some
classes similar to we generate in JAX-B, but where are these tools under?
These tools are available to you when you install JWSDP.
Basically we will use two tools for JAX-RPC API RI based web service
development.
ii) Wsdeploy – Used for generating service related configurations which are
required to deploy your service.
82
Mr. Sriman Web Services
Both these tools are shipped as part of JWSDP when you install and are
available under the below folder.
C:>Sun\JWSDP-2.0
| - jaxrpc
| - bin
| - wscompile.bat, wscompile.sh, wsdeploy.bat, wsdeploy.sh
As we know the Consumer will send’s the request to the Provider requesting
for some data or processing. Here sending the request to the Provider is
nothing but invoking a method on the Provider for e.g. in the above code he
will call getBookPrice method to get the price of the book.
While calling this method, the consumer needs to send data required for
executing the method. Does the consumer need to send the Java type data?
He shouldn’t rather send XML equivalent of it for example if it is rpc-encoded,
the request XML will look as shown below.
<getBookPrice>
<isbn xsi:type=”xs:string>ISBN1001</isbn>
</getBookPrice>
“RPC” stands for remote procedural call, so the request XML the consumer is
sending would exactly represent like a method call with root element equal to
method name and parameters of the method as sub-elements.
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Header/>
<soap:Body>
<getBookPrice>
<isbn xsi:type=”xs:string>ISBN1001</isbn>
</getBookPrice>
</soapy:Body>
</soap:Envelope>
And the above SOAP XML will be placed inside the HTTP Message and sends a
HttpRequest to Provider.
83
Mr. Sriman Web Services
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-
encoding">
Payload
<soap:Header/>
<soap:Body>
<getBookPrice>
<isbn xsi:type=”xs:string>ISBN1001</isbn>
</getBookPrice>
</soapy:Body>
</soap:Envelope>
Now the above Http Request message would be sent to the Provider. On the
Provider side, they should be some person acting as a listener who can receive
the above HTTP Request. This listener at the Provider end typically would be a
Servlet as he is the best person to process HTTP requests.
SOAP Processors are the components who know how to parse a SOAP XML,
SOAP Processors will process the SOAP Headers if any and then extracts the
Body of the Soap Message. The body of the SOAP XML is business XML. Now
the SOAP Processors don’t know how to process business XML, so they
delegate this XML to Binding classes.
Binding classes are the classes who know how to convert XML to Java Object.
Now these classes convert the XML into Java Object from which, runtime takes
the data and passes them as parameters in calling the Implementation class
methods.
84
Mr. Sriman Web Services
Now here comes the question, based on what I need to generate the binding
classes, if you analyze carefully the above explanation, the request XML would
be converted into Java Object and would be passed as Web service method
parameters, which means the XML would be converted to method parameters,
this indicates I need to generate binding class for every web service method
parameters. So, while running the wscompile tool, I need to pass the input as
SEI interface, so that the tool will loads the SEI interface and identifies the
methods and their parameters and based on the message exchange format, it
will generates the binding classes.
Wscompile tool is proprietary tool shipped by JWSDP for building JAX-RPC SI.
From the above, we understood we need to give input to the wscompile tool as
SEI interface, but passing the Interface information differs from Vendor who
ships the tool.
In our case, JWSDP provided wscompile tool will of course takes the SEI
interface as input, but not directly rather you need to configure this
information in a configuration file called config.xml. It is similar to web.xml in
which you configure the Servlet information. But unfortunately this config.xml
is not common configuration file that every tool uses and it is specific to JAX-
WS API RI implementation and is provided by vendor.
Now developer in order to run the wscompile tool, he needs to configure the
SEI interface, implementation class, package name, Service Name,
targetNameSpace and typeNameSpace in the configuration file and needs to
provide this as input.
85
Mr. Sriman Web Services
config.xml
Along with configuration file he needs to specify some more switches while
running the command as described below.
86
Mr. Sriman Web Services
<modelfile location="mymodel.xml.gz"/>
With the above command, the wscompile reads the contents of the config.xml
and identifies the SEI interface and Implementation class and validates against
all the rules in implementing them. Once those are valid, it starts reading the
methods of the SEI interface and generates the following artifacts
87
Mr. Sriman Web Services
If you observe the above, the WSDL has been generated taking the input as
Java classes and hence this is called Contract Last approach.
With this above we generated all the classes that are required to facilitate the
conversion of XML to Java and Java to XML at the Provider side for every
method.
d) Write jaxrpc-ri.xml
After generating the necessary binding classes to expose our class as service,
we need to configure the endpoint information of our service in a configuration
file called jaxrpc-ri.xml
As how you write web.xml to attach for a Servlet an URL to access, for even
your Web service class we need to attach an URL to expose it as an service so
that Consumers can access the service by using the URL we specified here.
Note: - The file name should be jaxrpc-ri.xml and it is mandatory to use the
same file name you should place this file under WEB-INF directory only.
88
Mr. Sriman Web Services
<endpoint
name="Store"
displayName="Get Book Price"
description="Used for finding price of book"
wsdl="/WEB-INF/StoreService.wsdl"
interface="com.store.service.Store"
implementation="com.store.service.StoreImpl"
model="/WEB-INF/wsdl-rpc-enc.xml.gz"/>
<endpointMapping
endpointName="Store"
urlPattern="/store"/>
</webServices>
After writing the jaxrpc-ri.xml file, we need to run wsdeploy tool which
generates web service deployment descriptor that carries the information
describing the service, which is used for servicing the request from the
consumer.
While running this tool we need to give the input as war of our application. So
first we need to export the project and then need to run the wsdeploy tool by
giving this war as input shown below.
The above command reads the contents of BookWeb.war and identifies the
web.xml and jaxrpc-ri.xml. It reads the contents of web.xml and updates it
with some more additional configuration. Along with this it uses the jaxrpc-
ri.xml as input file and generates web service deployment descriptor jaxrpc-ri-
runtime.xml which contains the configuration related to service we are
exposing.
These two files will be generated and placed inside the target.war. Now we can
either directly deploy the target.war on the Application Server or extract the
target.war and copy web.xml and jaxrpc-ri-runtime.xml and can paste our
eclipse project and deploy from eclipse as well.
89
Mr. Sriman Web Services
Deploy the war and start your server and you should be able to access the
service.
web.xml
<servlet>
<servlet-name>Store</servlet-name>
<servlet-class>com.sun.xml.rpc.server.http.JAXRPCServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Store</servlet-name>
<url-pattern>/store</url-pattern>
</servlet-mapping>
Once the request has been received by the JAXPRCServlet, it would process the
HTTP Headers and then tries to extract the payload of it. The payload would be
SOAP XML, as Servlet cannot understand the SOAP XML; it needs to find the
relevant SOAP Parser’s to process it.
90
Mr. Sriman Web Services
jaxrpc-ri-runtime.xml
From the above configuration it picks up the Tie class name matching the Servlet
Path and forwards the request to the Tie for further processing.
Tie class has the logic for processing the SOAP XML, and extracts the actual XML
from the SOAP Body and then passes it to request SOAP serializers/De-Serializers
to convert into Java Object. Then passes the Object data as input to the Service
method. Once the Service method finishes processing, it returns Java Object data
as response to the Tie. Now Tie converts this back into XML and then into SOAP
XML and places it into HTTP Response Message and sends back it to the
Consumer.
91
Mr. Sriman Web Services
Create a new Dynamic Web Project in eclipse, expand the Project directory and
navigate into WebContent/WEB-INF/lib directory. Copy/paste all the jaxrpc jar’s
that are given in Jar bundles folder to the above lib project. Configure the Build
path by right clicking on the project, select configure build path and switch to
libraries tab and add all the jar’s in the lib to the Project class Path
New Dynamic Web Project
Write SEI Interface
92
Mr. Sriman Web Services
As explained earlier WSCOMPILE tool will generates the binding classes by taking
the config.xml as input. As you have to generate the binding classes into
wscompile
Run the
Project Src directory, you need to run the tool from Project directory. So you
need to set First of all the System Path pointing to the location of WSCOMPILE
bat file, and then switch to the Project directory and run WSCOMPILE as shown
below.
93
Mr. Sriman Web Services
Cd D:\Folder1\Folder2\BookWeb
If you execute DIR command under this directory you must see “src” till then
you need to navigate.
Drag and Drop WSDL and Model files generated into WebContent\WEB-INF
directory
94
Mr. Sriman Web Services
Write jaxrpc-ri.xml
95
Export the project as WAR
96
Mr. Sriman
Web Services
Mr. Sriman Web Services
97
Mr. Sriman Web Services
98
Mr. Sriman Web Services
As indicated earlier, you can develop a Web service in two approaches contract
first and contract last. We already discussed about contract last approach. Now
we are trying to build the Provider using contract first approach.
By looking at the WSDL – PortType we can create the SEI interface and based on
the operation input and output types we can create method with parameters and
return types. We need serializers and de-serializers to map incoming XML data to
method parameters and return value of the method to XML back.
99
Mr. Sriman Web Services
100
Mr. Sriman Web Services
Instead of developer writing the above classes, we can run the wscompile tool
which is shipped as part of JWSDP by giving input as WSDL. Now the wscompile
will loads the WSDL document and reads various elements of WSDL and
generates the required classes to build the Web service. Following are the classes
generated when we run wscompile.
Service Interface and Impl Required for building Consumer (we can ignore
this class if we are building Provider)
101
Mr. Sriman Web Services
As we know wscompile will not directly takes the WSDL, rather we need to write
the config.xml and need to configure WSDL location in it rather than SEI interface
and Implementation. Now give this config.xml as input to wscompile so that it
generates the classes required to build the Web service.
config.xml
<configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
<wsdl location="http://localhost:8080/StoreWeb/store?WSDL"
packageName="com.store.service">
</wsdl>
</configuration>
As all the classes are available to build the Service, we need to write now the
Implementation class implementing the SEI interface. Then we need to write the
jaxrpc-ri.xml, which attaches url to the endpoint.
Now export the project as war and run wsdeploy tool by giving war as input
102
Mr. Sriman Web Services
From the wsdl, we need to generate Java classes required to build the
Service. As we know, wscompile can generate the required classes but it
Write config.xml
But as opposed to the earlier approach we don’t have Java classes, rather
we need to configure the location of WSDL in config.xml to generate Java
classes as shown below.
103
Mr. Sriman Web Services
Now we need to run the wscompile tool to generate classes by giving input
as config.xml
(If you observer –cp is not there as we are not providing any classes as
tool
Note: - We need to place this file in WEB-INF directory and the file name
should be jaxrpc-ri.xml only.
Write jaxrpc-ri.xml
104
Mr. Sriman Web Services
Now on the generated war, you need to run the wsdeploy tool. This tool will
take the input as PurchaseOrderWeb.war and generates the specified war as
Run wsdeploy
output.
105
106
Deploy and Test Copy jaxrpc-ri-runtime.xml and
web.xml to WEB-INF
Mr. Sriman
Web Services
Mr. Sriman Web Services
Dashboard
Let’s try to understand how to develop each of them in the following section.
So, to convert Object to XML and place it SOAP XML, we need serializers and de-
serializers even at the consumer side as well. But how do we know what are the
inputs to the Provider and what is the output from it. Because based on the
Input/Output and number of operations only we can generate the binding
classes.
As the Provider was built, we can access the WSDL of the Provider. If we look at
the WSDL document, it’s PortType represents the SEI Interface and its
operations defines the methods of the SEI interface and Input/Output represents
the parameters and return values of each method.
107
Mr. Sriman Web Services
So, WSDL contains the entire information about the service. If we give WSDL as
input to the wscompile tool it will generates all the required classes like
request/response structs, soap serializers/de-serializers etc. But to access the
Provider, we need an implementation for the SEI interface. The implementation
of the SEI interface should contain the logic for sending the request and getting
the response from the Provider. For this wscompile will generates a Stub, it is
nothing but implementation of SEI interface at the consumer side. The presence
of this Stub is abstracted from the programmer by giving a factory called
Service.
config.xml
<configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
<wsdl location="http://localhost:8080/StoreWeb/store?WSDL"
packageName="com.store.service">
</wsdl>
</configuration>
Now run the wscompile tool by giving the above config.xml as input. While
running as we are developing the consumer, we need to use –gen:client as we
need consumer side binding classes. As we don’t have any classes right now we
don’t need to specify –cp. The command reference and set of classes that would
be generated are shown below.
108
Mr. Sriman Web Services
If you open the generated Stub class it clearly indicates as implementing from SEI
interface and it overrides the methods in the SEI interface, but those methods will
not have business logic, rather they have the logic for converting object data into
XML, and send over the HTTP connection to the Provider.
package com.store.service;
_myStore_getBookPrice_RequestStruct.setString_1(string_1);
_send((java.lang.String) _getProperty(ENDPOINT_ADDRESS_PROPERTY),
_state);
com.store.service.Store_getBookPrice_ResponseStruct
_myStore_getBookPrice_ResponseStruct = null;
Object _responseObj = _state.getResponse().getBody().getValue();
if (_responseObj instanceof SOAPDeserializationState) {
_myStore_getBookPrice_ResponseStruct =
(com.store.service.Store_getBookPrice_ResponseStruct)((SOAPDeserializationStat
e)_responseObj).getInstance();
} else {
_myStore_getBookPrice_ResponseStruct =
(com.store.service.Store_getBookPrice_ResponseStruct)_responseObj;
}
return _myStore_getBookPrice_ResponseStruct.getResult();
// skipped code for clarity
109
Mr. Sriman Web Services
Now write test class in which create the Object of SEI interface, we know the
Implementation of SEI interface at the consumer side is Stub. Rather than we
directly exposed to the generated Stub, it is being created by Service. Blow is the
code snippet shows you how to build the program
package com.store.service;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
110
Mr. Sriman Web Services
111
Mr. Sriman Web Services
Create a Config folder in the Project directory; create config.xml inside the
config folder created. Now configure the wsdl location of the provider for whom
you want to generate the binding classes.
Write config.xml
112
Mr. Sriman Web Services
Navigate to the Project directory. Set the Path pointing to the location of
wscompile tool. Run the wscompile tool by giving above config.xml as input.
Note: - While running the wscompile tool, the provider should be up and
running.
Run wscompile
Create Test class, in which create the Object of SEI interface with the help of
Service as shown below. And run the client will be able to get the data from the
Provider.
Create Test class
113
Mr. Sriman Web Services
In order to generate the Stub class at runtime, we need to use the JAX-RPC API
specific classes, who know how to generate it.
First the programmer has to browse the WSDL document. In the WSDL
document he needs to identify the PortType, operations and input/output
messages, from which he needs to build the SEI interface with methods,
parameters and return types.
Once the SEI interface has been build, we need to use couple of JAX-RPC API
classes to provide the Stub implementation of the SEI interface. The steps for
the same are detailed below.
3) Call getPort method – On the service created above, we need to call the
getPort method by passing qName of the Port and SEI Interface Type. By
reading the Port definition, the getPort method will try to generate a Stub
class at runtime by implementing the SEI interface which is passed as
reference and returns the Object of it.
114
Mr. Sriman Web Services
Once we have the port, we can any methods on the Port which inturn makes
a remote call to the Provider. The following code snippet shows how to build
a Dynamic Proxy based client.
package com.store.service.dp.client;
115
Mr. Sriman Web Services
2) Create the Service – We need to create the Service from the ServiceFactory.
While create the Service, we need to give the input as qName of the Service
from the WSDL Service element.
3) Create the call – Call is the Object which allows you to call a remote
procedure on the Provider. To create the Call object, we need to call
createCall method on the Service Object. While creating the call object, to
the createCall() method, we need to pass the Port Name from which you
want to get the Call object as shown below.
4) Set the parameters on the Call object – The call just we retrieved is a generic
Call object which is not pointing to any specific endpoint. Now we need to set
the values like method name, Target Endpoint Address, Input/Ouput
paramters etc.
methodCall.setTargetEndpointAddress(“URL”);
SOAPACTION_URI_PROPERTY
SOAPACTION_USE_PROPERTY
ENCODING_STYLE_PROPERTY
6) Invoke the method on the Call Object – To invoke the remote procedure on
the service, we need to call Call.invoke(new Object[]{}) by passing required
inputs as Object[] where it returns the response back to the user.
The below code snippet shows the complete example on the same.
116
Mr. Sriman Web Services
package com.store.service.dii.client;
getBookPriceCall.setProperty(Call.ENCODINGSTYLE_URI_PROPERTY,
"http://schemas.xmlsoap.org/soap/encoding/");
Object price = getBookPriceCall.invoke(new Object[] { "ISBN1001"
});
System.out.println("Price : " + price);
}
117
Mr. Sriman Web Services
WSDL
118
Mr. Sriman Web Services
WSDL plays a crucial role even in Web Service development, where service can
build from the WSDL document. Only way of consumer knowing the information
about the provider is by looking at the WSDL document. As per BP 1.1, WSDL 1.1
is used in describing the information about the service. WSDL 2.0 is also has been
finalized, but yet no one started adopted it, and if we uptake WSDL 2.0,
interoperability would become a challenge.
WSDL contains total six elements. Let us try to understand various elements of the
WSDL document. WSDL is also an XML, every XML will starts with PROLOG and
every XML has a root element. If WSDL is also an XML document, it also starts with
PROLOG and has root element <definitions>. Including <definitions> there are six
elements.
119
Mr. Sriman Web Services
For e.g.
I have a Provider shown below who has a method enroll taking the parameter as
MemberShipInfo and returning MemberCard
<types>
<xsd:schema targetNameSpace = “http://ebay.in/sales/types”>
<xsd:complexType name=”MemberShipInfo”>
<xsd:sequence>
<!-- elements representing attributes of the class -->
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name=”MemberCard”>
<xsd:sequence>
<!-- elements representing attributes of the class -->
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</types>
Note: - In the above types section, we have an inline XSD document. And all the
complex types are declared under target namespace.
120
Mr. Sriman Web Services
For e.g.
<message name=”PolicyRegistration_enroll”>
<part name="memberInfo" type="pt:MemberInfo"/>
<part name="policyInfo" type="pt:PolicyInfo"/>
</message>
<message name="PolicyRegistration_enrollResponse>
<part name="result" type="pt:MemberCard"/>
</message>
A message has name which allows to refer/identify it. Generally it would be named
as SEI Interface_<method> – Input message and SEI
Interface_<method>Response – Output message.
Note: - In the above message “pt:” represents the prefix namespace under which
the complex types are declared under.
121
Mr. Sriman Web Services
For e.g.
For the earlier show SEI interface, the PortType representation is shown below.
<PortType name="PolicyRegistration">
<operation name="enroll">
<input message="tns:PolicyRegistration_enroll"/>
<output message="tns:PolicyRegistration_enrollResponse"/>
</operation>
</PortType>
In the above PortType declaration, we declared one operation enroll who has
input/output as messages, which are referring to the messages we declared under
messages section.
Note:- “tns:” represents the namespace under which the <message> elements are
declared. Generally, for a WSDL also we have targetNameSpace declaration and all
the message, PortType and other elements of WSDL will be by default binding to
that targetNameSpace.
SoapAction: - While consumer sending the request to the provider, he will place
soapAction (of the method we want to invoke from WSDL) in the HTTP Request
header. Once the Provider has received it, he will identify the respective method to
invoke based on the soapAction value in the request header.
122
Mr. Sriman Web Services
For e.g.
In the above binding we define the transport type as soap over http. Along with
this we specifying the style and use as rpc and encoded respectively.
For e.g.
<service name="PolicyRegistrationService">
<port name="PolicyRegistrationPort" binding="tns:PolicyRegistrationBinding">
<soap:address location="REPLACE_WITH_ACTUAL_URL"/>
</port>
</service>
123
Mr. Sriman Web Services
Apache
Axis
124
Mr. Sriman Web Services
2) Copy mail.jar and activation.jar files from “Jar Bundles”\Apache Axis\ folder to
c:\axis-1_4\lib directory.
125
Mr. Sriman Web Services
4) Copy all the Jar’s from Jar Bundles\Apache Axis folder to project WEB-INF\lib
directory
126
Copy contents of WEB-INF folder to Copy all the .Java files to “src”
Project WEB-INF
127
Mr. Sriman
Web Services
Mr. Sriman Web Services
6) With the above we completed configuring the project, now we need to check
the environment. To do it first deploy the Project on the Tomcat server
configured in IDE as shown below.
7) Start the Server and browse to the context root of the application
128
Mr. Sriman Web Services
http://<adminhost>:<port>/PolicyWeb
This will display the happy axis home page shown below. You can click on
validate link will validate and shows whether axis has been configured properly
or not.
1) As we are building the Provider using contract first approach. We need to start
development with the WSDL. I want to build a PolicyRegistration service, it
contains a method enroll which takes the parameters as MemberInformation
and PolicyInformation and returns MemberCard to the consumer. The Java
equivalent of it is shown below.
Now we need to write the WSDL document which describes the information for
the above service. The input/output types of the methods MemberInformation,
129
Mr. Sriman Web Services
Create the WSDL document under WEB-INF folder. The WSDL for the above
described service is shown below.
<xsd:complexType name="MemberInformation">
<xsd:sequence>
<xsd:element name="ssn" type="xsd:string" />
<xsd:element name="name" type="xsd:string"
/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="PolicyInformation">
<xsd:sequence>
<xsd:element name="policyId"
type="xsd:string" />
<xsd:element name="tenure" type="xsd:int" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="MemberCard">
<xsd:sequence>
<xsd:element name="enrollmentId"
type="xsd:string" />
<xsd:element name="coverageType"
type="xsd:int" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
130
Mr. Sriman Web Services
<wsdl:message name="PolicyRegistration_enroll">
<wsdl:part name="mInfo" type="pt:MemberInformation" />
<wsdl:part name="pInfo" type="pt:PolicyInformation" />
</wsdl:message>
<wsdl:message name="PolicyRegistration_enrollResponse">
<wsdl:part name="result" type="pt:MemberCard" />
</wsdl:message>
<wsdl:portType name="PolicyRegistration">
<wsdl:operation name="enroll" parameterOrder="mInfo pInfo">
<wsdl:input message="tns:PolicyRegistration_enroll" />
<wsdl:output
message="tns:PolicyRegistration_enrollResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="PolicyRegistrationSOAPBinding"
type="tns:PolicyRegistration">
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="enroll">
<soap:operation
soapAction="http://licindia.org/policy/wsdl/enroll" />
<wsdl:input>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://licindia.org/policy/wsdl"
use="encoded" />
</wsdl:input>
<wsdl:output>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://licindia.org/policy/wsdl"
use="encoded" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="PolicyService">
<wsdl:port binding="tns:PolicyRegistrationSOAPBinding"
name="PolicyRegistrationPort">
<soap:address location="http://www.example.org/" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
131
Mr. Sriman Web Services
2) After writing the WSDL, we need to generate Java classes out of It. The
classes would be generated based on the PortType, their input/output message
and bindings sections. Along with that it will generate binding classes required
to facilitate the serialization/de-serialization of objects to XML.
To generate the Java classes from WSDL document, Axis has provided a tool
called WSDLToJava, we need to run this by giving WSDL as an Input. Unlike
wscompile tool, WSDLToJava is not a “.bat” file rather it’s a Java class we need
to run by setting the class path to all the jars in c:\axis-1_4\lib.
First we need to prepare the CLASSPATH variable pointing to the entire jar’s in
the axis distribution lib directory as shown below.
set AXISPATH=c:\axis-1_4\lib
set AXISCLASSPATH=%AXISPATH%\activation.jar;%AXISPATH%\axis-
ant.jar;%AXISPATH%\axis.jar;%AXISPATH%\commons-discovery-
0.2.jar;%AXISPATH%\commons-logging-
1.0.4.jar;%AXISPATH%\jaxrpc.jar;%AXISPATH%\log4j-
1.2.8.jar;%AXISPATH%\mail.jar;%AXISPATH%\saaj.jar;%AXISPATH%\wsdl4j
-1.5.1.jar
When we run the above command it will generates the following files
PolicyRegistration SEI Interface
PolicyRegistrationSOAPBindingImpl Implementation class with empty
logic in methods
PolicyRegistrationSOAPBindingStub Consumer class (not required)
PolicyService, PolicyServiceLocation Consumer classes (not required)
MemberCard, MemberInformation, Input/Output classes containing
PolicyInformation serialization logic as well.
Deploy.wsdd, UnDeploy.wsdd These two files web service
deployment descriptors that are
used for deploy and undeploy of the
service.
132
Mr. Sriman Web Services
If you refer to the request processing model below, similarly JAX-RPC API
JAXRPCServlet which acts as an engine in processing the request. Here the
AxisServlet plays a crucial role in handling and processing the request. When a
request comes to AxisServlet, it looks up in server-config.wsdd at runtime to
identify the respective Implementation class to process the request.
But this file will not be generated when we run WSDL2Java instead we need to
generate this file on fly in the server to deploy the service; this server-
config.wsdd file will be generated on the server side based on the information
described in deploy.wsdd.
The AdminClient will reads the contents of the deploy.wsdd and upload it to
the AxisServlet where the AxisServlet upon receiving the request will
generates the server-config.wsdd containing our service information.
6) Now browse the Happy Axis homepage and click on the list. It will show our
service information as well. Click on the WSDL will generate the WSDL
document onfly.
133
After creating the Project
write the WSDL File under
134
WEB-INF directory
Mr. Sriman
First build the AXISCLASSPATH pointing to the axis distribution lib directory
Now switch to the Project directory and run the WSDL2Java command
This will generates the classes and deployment descriptors that are required
to build the service as shown here
Run WSDL2Java
135
Write Drag & Drop deploy.wsdd and undeplloy.wsdd into WEB-
Implementation INF folder
136
logic
Mr. Sriman
Web Services
Mr. Sriman Web Services
Now test your service by accessing the happy axis home page and browse the WSDL.
137
Mr. Sriman Web Services
JAX-WS
138
Mr. Sriman Web Services
After BP1.1, WS-I has released BP 1.2 and BP 2.0 specifications as well. JAX-WS
API adopts even the BP 1.2 and BP 2.0 as well.
Then came Java added its support to web services by releasing JAX-RPC 1.0 API.
After few months of its use, JCP (Java community folks) felt few modifications are
required for the API and has released JAX-RPC 1.1. After few years of its use, JCP
folks wanted to build a better version: JAX-RPC 2.0
A primary goal was to align with the industry standards, but the industry is doing
message oriented web services (async req/reply). But Java supports JAX-RPC
where RPC represents Remote Procedural calls which mean sync req/reply. So,
Sun has added its support to Message oriented web services by renaming “RPC”
to “WS” which results in JAX-WS API.
Let’s talk about what are common between JAX-RPC and JAX-WS API.
1) JAX-RPC API uses SOAP 1.1 over HTTP 1.1 and JAX-API still supports SOAP 1.1
over HTTP 1.1. This means the same message can still flow across the wire. So
interoperability is not affected.
2) JAX-RPC supports WSDL 1.1 and JAX-WS along with WSDL 1.1 it even
supports WSDL 2.0
139
Mr. Sriman Web Services
Now let us talk about the differences between JAX-RPC and JAX-WS API’s
a) SOAP: - JAX-RPC supports SOAP 1.1. JAX-WS also supports SOAP 1.1 along
with that it supports SOAP 1.2 and SOAP 2.0.
b) XML/HTTP: - WSDL 1.1 specification has support for HTTP Binding. It means
you can send XML messages over the HTTP without SOAP. JAX-RPC ignored
the HTTP binding, whereas JAX-WS added support for Http binding.
c) WS-I’s Basic Profiles: - JAX-RPC API supports WS-I Basic Profile 1.0. JAX-WS
API supports WS-I Basic Profile 1.1.
d) New Java features: - Minimum JDK that is required to work with JAX-RPC API
is Jdk 1.4. But JAX-WS relies on many of the features of Java 5. Java 5 adding
support to JAX-WS, it even retains support for JAX-RPC API.
e) The data mapping model: - JAX-RPC has its own data mapping model, which
covers about 90 percent of all schema types. JAX-WS’s data mapping model is
JAX-B.
f) The interface mapping model: - JAX-WS API makes use of Java 5 and
introduced new interfaces to support Asynchronous programming.
h) The handler model: - JAX-RPC handlers use SAAJ 1.2 API to work with SOAP
XML whereas JAX-WS handlers rely on SAAJ 1.3.
By the above we understood the differences between JAX-RPC API and JAX-WS API
now let us understand how to build a JAX-WS API based SI implementation service
using contract last approach.
140
Mr. Sriman Web Services
The following section shows the detailed steps of creating a JAX-WS API RI based
service using contract last approach. We will compare various steps in comparison
with JAX-RPC SI Implementation to better understand them.
a) Write SEI Interface – As you know from the Programming point of view SEI
interface acts as a contract between Provider and Consumer. As it is contract
last approach, the development starts with SEI Interface. We need to follow
certain rules in writing SEI Interface described below.
141
Mr. Sriman Web Services
Now following the above rules let’s write an SEI interface shown below.
package com.tw.service;
In the above code we have written an SEI Interface name reservation and we
indicated it as SEI interface with @WebService annotation. Along with that, we
marked it name attribute indicating the name of the endpoint and
targetNamespace which is the WSDL Namespace of that service.
You can declare typeNamespace for the Input and Output of a service method
using @WebParam and @WebResult as well.
142
Mr. Sriman Web Services
package com.tw.service;
import javax.jws.WebService;
@WebService(endpointInterface = "com.tw.service.Reservation")
public class ReservationImpl {
public Ticket doBooking(PassengerInfo pInfo, JourneyInfo jInfo) {
Ticket ticket = new Ticket();
ticket.setPnr("PNR24242");
ticket.setStatus("CONFIRMED");
return ticket;
}
}
143
Mr. Sriman Web Services
package com.tw.service;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import com.tw.business.JourneyInfo;
import com.tw.business.PassengerInfo;
import com.tw.business.Ticket;
@WebService
public class ReservationImpl {
@WebMethod(operationName = "doBooking", action =
"http://irctc.org/reservation/wsdl#doBooking")
@WebResult(name = "return", targetNamespace =
"http://irctc.org/reservation/types")
Ticket doBooking(
@WebParam(name = "pInfo", targetNamespace =
"http://irctc.org/reservation/types") PassengerInfo pInfo,
@WebParam(name = "jInfo", targetNamespace =
"http://irctc.org/reservation/types") JourneyInfo jInfo) {
Ticket ticket = new Ticket();
ticket.setPnr("PNR24242");
ticket.setStatus("CONFIRMED");
return ticket;
}
}
Rather than we writing the binding classes to perform this we use the tool that
is provided by JWSDP, nothing but wsgen. Wsgen will takes the input as the
annotated classes and generates binding classes to perform marshaling and
un-marshalling.
144
Mr. Sriman Web Services
When we install JWSDP it has provided two tools to work on JAX-WS API
RI based web services those are
C:\Sun\Jwsdp-2.0
|-Jaxws
|-lib
|-bin – wsgen, wsimport
Even when we install JDK 1.6 also these tools will be shipped as part of
JDK under bin directory.
To generate binding classes from Java classes we need to use wsgen tool.
Wsgen will take the annotated Implementation class as input and
generates binding classes as output. Wsgen tool will directly takes the
Implementation class (as SEI interface is optional) as input and generates
binding class, we don’t need separate configuration file, because we
provided configuration information about the class using annotations
directly written at class level.
145
Mr. Sriman Web Services
When we run the above command, it just generates two JAXB binding
classes as output, one for converting input xml to object and other for
converting object data back to xml.
<endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime'
version='2.0'>
<endpoint
name='Reservation'
implementation='com.tw.service.ReservationImpl'
url-pattern='/bookTicket'/>
</endpoints>
If we look at the contents of the above file, it is straight forward and contains
Implementation class name and url-pattern with which you want to access it.
Along with the servlet, we need to configure an Listener in the web.xml, the
listener will be fired when the application context has been initialized and
checks for the file sun-jaxws.xml under WEB-INF. As the file is mandatory, if
that file misses in WEB-INF, it will not deploys the application rather throws
error while starting the application itself.
146
Mr. Sriman Web Services
web.xml
147
Mr. Sriman Web Services
148
149
Write Input/output classes of the Service Copy all the Jars into lib
Mr. Sriman
Web Services
Mr. Sriman Web Services
150
Mr. Sriman Web Services
To generate Binding classes we need to run the tool wsgen. We don’t need
to write any config.xml rather it takes the Implementation class as input,
because already the classes are annotated with configuration information.
Generate Binding classes
In this file we will provide the endpoint configuration, means attaches URL
to the Service.
Write sun-jaxws.xml
Write web.xml
151
Mr. Sriman Web Services
With the above we should be able to access the Dashboard and WSDL of the
Service as well. You can test it using SOAP UI.
Using this WSDL document we can generate the classes that are required to
create the Service.
152
Mr. Sriman Web Services
Note: - If you are developing a JAX-WS based service, the default encoding
format will be document/literal. If it is document literal, you XML elements
itself will become the input of the web service method and output of the web
service method. So in the types section rather than declaring complex types,
you need to declare elements. Messages refer to elements rather than types
as shown below.
153
Mr. Sriman Web Services
<xsd:element name="TransactionDetails">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="balance"
type="xsd:float" />
<xsd:element name="transactionCode"
type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="withdraw">
<wsdl:part element="bt:WithdrawlInfo" name="withdrawInfo" />
</wsdl:message>
<wsdl:message name="withdrawResponse">
<wsdl:part element="bt:TransactionDetails"
name="transactionDetails" />
</wsdl:message>
<wsdl:portType name="Bank">
<wsdl:operation name="withdraw">
<wsdl:input message="tns:withdraw" />
<wsdl:output message="tns:withdrawResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="BankBinding" type="tns:Bank">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="withdraw">
<soap:operation
soapAction="http://icicibank.org/service/wsdl/withdraw" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="BankService">
<wsdl:port binding="tns:BankBinding" name="BankPort">
<soap:address location="http://www.example.org/" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
154
Mr. Sriman Web Services
b) Generate Java and Binding classes from WSDL – We need to give WSDL
as input and should generate required Java classes and binding classes as
output. As we know JWSDP has provided two tools wsgen and wsimport, we
need to use wsimport to generate java classes from WSDL.
It takes directly the WSDL as input and generates the classes supporting to
build both Provider as well as Consumer. As we need to build provider, we can
use them to build provider.
c) Write Implementation class for SEI interface – Follow all the rules and
write the Implementation class declaring the endpointInterface as the
generated interface as shown below.
package org.icicibank.service.wsdl;
import javax.jws.WebService;
import org.icicibank.service.types.TransactionDetails;
import org.icicibank.service.types.WithdrawlInfo;
@WebService(endpointInterface = "org.icicibank.service.wsdl.Bank")
public class BankImpl {
<endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime'
version='2.0'>
<endpoint
name='Bank'
implementation='org.icicibank.service.wsdl.BankImpl'
url-pattern='/withdraw'/>
</endpoints>
155
Mr. Sriman Web Services
web.xml
156
Mr. Sriman Web Services
157
Mr. Sriman Web Services
158
159
Write Implementation class Run wsimport tool
Mr. Sriman
Web Services
Mr. Sriman Web Services
Write sun-jaxws.xml
The url of the WSServlet should match with the url pattern of the endpoint
configured in sun-jaxws.xml
Write web.xml
Deploy your project, start the server and access the Dashboard and browse the
WSDL. Use soap ui tool to test it.
a) Stub based
b) Dispatch API
160
Mr. Sriman Web Services
Out of the above two, most of the projects use stub based consumer and
following section describes how to build a stub based consumer for JAX-WS
Provider.
Using the WSDL, we can generate the classes supporting for development of
consumer. So, run the wsimport tool by giving WSDL as input, it will generate
classes for building both consumer and provider.
b) Create the consumer class, which sends the request to provider with
inputs – Once you generate all the classes, we need to build a Consumer
class which will creates the Object of Service and call getPort() method to get
the Stub object.
Once the Stub object is there we can call methods on the Stub object to send
the request to the provider.
161
Mr. Sriman Web Services
package com.bank.client;
TransactionDetails td = port.withdraw(withdrawInfo);
System.out.println("Balance : " + td.getBalance());
}
}
162
Mr. Sriman Web Services
Run wsimport by giving dynamic wsdl url as input. It will generates classes
required for both Provider as well as client.
Run wsimport
163
Mr. Sriman Web Services
Test class is nothing but the class in which you want to call the service.
Create generated Service class Object and then call getPort() method on it
which will generates the Stub object. As you know Stub is the
implementation of SEI interface, you can assign it to SEI interface reference
variable. Now call the methods, indeed calls the methods on generated Stub
class.
Create a Test class
a) Dynamic Proxy
b) Dispatch API
We already saw how to work on Dynamic Proxy based consumer, now we are
trying to understand how to work with Dispatch API Client.
The dispatch API is a low level API that requires clients to construct messages or
message payloads using XML based technology to send request to provider.
164
Mr. Sriman Web Services
For invoking non-soap based services like JAX-WS XML Binding provider or REST
we use dispatch API.
The below code provides you an in-sight of how to work with Dispatch API client.
TransactOnlineDispatchClient.java
package com.bw.service.dispatch.client;
public class TransactOnlineDispatchClient {
private static final String TARG_NMSPC = "http://idbi.com/transaction/wsdl";
private static final String SERVICE_NM = "TransactOnlineService";
private static final String PORT_NM = "TransactOnlineSoapPort";
private static final String TYP_NMSPC = "http://idbi.com/transaction/types";
private static final String TRG_ENDPOINT_URL =
"http://localhost:8080/BankWeb/withdrawl";
165
Mr. Sriman Web Services
• RPC/encoded
• RPC/literal
• Document/encoded
• Document/literal
We have messaging models or programming models, which talks about how the
messages are being exchanged between consumer and provider, those are
“RPC” and message oriented programming models. There is no relation between
programming models and your exchanging styles. You can use any style with
any programming models.
Let us try to understand how a message typically looks like when we use
different messaging styles and their advantages and dis-advantages.
166
Mr. Sriman Web Services
14.9.1 RPC/Encoded
For the above SEI Interface here is the WSDL PortType and soap message
format.
RPC/encoded WSDL
<types>
<xsd:complexType name=”MemberInfo”>
….
</xsd:complexType>
<xsd:complexType name=”PolicyInfo”>
….
</xsd:complexType>
<xsd:complexType name=”MemberCard”>
….
</xsd:complexType>
</types>
<message name=”MemberRegistration_enroll”>
<part name=”mInfo” type=”typ:MemberInfo”/>
<part name=”pInfo” type=”typ:PolicyInfo”/>
</message>
<message name=”MemberRegistration_enrollResponse”>
<part name=”result” type=”typ:MemberCard”/>
</message>
<portType name=”MemberRegistration”>
<operation name=”enroll”>
<input message=”tns:MemberRegistration_enroll”/>
<output message=”tns:MemberRegistation_enrollResponse”/>
</operation>
</portType>
<soap:envelope>
<soap:header/>
<soap:body>
<enroll>
<mInfo>
<ssn xsi:type=”xsd:string>SSN22</ssn>
<age xsi:type=”xsd:int”>43</age>
</mInfo>
<pInfo>
…
</pInfo>
</enroll>
</soap:body>
</soap:envelope>
167
Mr. Sriman Web Services
14.9.1.1 Advantage
a) The WSDL is self-explanatory
b) The operation name appears in the message, so that the receiver has easy
time in dispatching this message to the implementation of the operation.
14.9.1.2 Dis-Advantage
a) The xsi:type encoding specified at the SOAP message is as extra overhead
which degrades the throughput performance
b) You cannot easily validate this message since the <ssn> and <age> are the
elements coming from <schema> and rest of the elements are derived from
WSDL definition.
14.9.2 RPC/Literal
The RPC/Literal WSDL looks almost same as RPC/Encoded WSDL except the
binding section will declares the style as RPC and use as literal.
<soap:envelope>
<soap:header/>
<soap:body>
<enroll>
<mInfo>
<ssn>SSN22</ssn>
<age>43</age>
</mInfo>
<pInfo>
…
</pInfo>
</enroll>
</soap:body>
</soap:envelope>
14.9.2.1 Advantage
a) The WSDL is still straight forward and self-explanatory
14.9.2.2 Dis-Advantage
a) You still cannot easily validate this message, since it has only <ssn> and
<age> coming from <schema>. Rest of the elements are derived from
WSDL.
168
Mr. Sriman Web Services
Is the document styles overcomes the dis-advantage with RPC style. Let us try to
understand.
14.9.3 Document/Encoded
Nobody follows this style. It is not WS-I complaint
14.9.4 Document/Literal
The WSDL for Document/Literal would be more or less looks similar to RPC, but
there are some small differences like under <types> section we need to define
elements rather than complexTypes. Messages takes the part’s as elements not
types as shown below.
<types>
<xsd:element name=”MemberInfo”>
<xsd:complexType>
….
</xsd:complexType>
</xsd:element>
<xsd:element name=”PolicyInfo”>
<xsd:complexType>
….
</xsd:complexType>
</xsd:complexType>
<xsd:element name=”MemberCard”>
<xsd:complexType>
….
</xsd:complexType>
</xsd:complexType>
</types>
<message name=”MemberRegistration_enroll”>
<part name=”mInfo” element=”typ:MemberInfo”/>
<part name=”pInfo” element=”typ:PolicyInfo”/>
</message>
<message name=”MemberRegistration_enrollResponse”>
<part name=”result” element=”typ:MemberCard”/>
</message>
<portType name=”MemberRegistration”>
<operation name=”enroll”>
<input message=”tns:MemberRegistration_enroll”/>
<output message=”tns:MemberRegistation_enrollResponse”/>
</operation>
</portType>
169
Mr. Sriman Web Services
<soap:envelope>
<soap:header/>
<soap:body>
<memberInfo>
<ssn>SSN22</ssn>
<age>43</age>
</memberInfo>
<policyInfo>
…
</policyInfo>
</soap:body>
</soap:envelope>
14.9.4.1 Advantage
a) There is no type encoding
b) You can finally validate the message with any XML validator. Everything with
in soap:body is defined in the <schema>
14.9.4.2 Dis-Advantage
a) The WSDL is getting bit complicated. This is a minor weakness.
b) The operation name in the SOAP message is lost. Without the name,
dispatching can be difficult and sometimes impossible.
c) WS-I only allows one child of the soap:body in the SOAP message.
14.9.5 Document/Wrapped
The document literal seems to be merely fix all the dis-advantages of rpc/literal
model. We can now validate the soap message. But we lost the operation name.
Is there anything you can do to improve upon this? Yes, it is called
Document/Wrapped.
170
Mr. Sriman Web Services
<types>
<xsd:element name=”enroll>
<xsd:complexType>
<xsd:element name=”mInfo” type=”typ:MemberInfo”/>
<xsd:element name=”pInfo” type=”typ:PolicyInfo”/>
</xsd:complexType>
<xsd:element>
<xsd:element name=”enrollResponse>
<xsd:complexType>
<xsd:element name=”result” type=”typ:MemberCard”/>
</xsd:complexType>
<xsd:element>
<xsd:complexType name=”MemberInfo”>
….
</xsd:complexType>
<xsd:complexType name=”PolicyInfo”>
….
</xsd:complexType>
<xsd:complexType name=”MemberCard”>
….
</xsd:complexType>
</types>
<message name=”enroll”>
<part name=”enroll” element=”typ: enroll”/>
</message>
<message name=”enrollResponse”>
<part name=”result” element=”typ: enrollResponse”/>
</message>
<portType name=”MemberRegistration”>
<operation name=”enroll”>
<input message=”tns:enroll”/>
<output message=”tns:enrollResponse”/>
</operation>
</portType>
171
Mr. Sriman Web Services
<soap:envelope>
<soap:header/>
<soap:body>
<enroll>
<memberInfo>
<ssn>SSN22</ssn>
<age>43</age>
</memberInfo>
<policyInfo>
…
</policyInfo>
</enroll>
</soap:body>
</soap:envelope>
14.9.5.1 Advantage
a) There is no type encoding
b) Everything that defines under the soap:body is defined by the schema. You
can validate the soap message with any of the XML validator
c) Once again you have method name in the soap message
d) Document/literal is WS-I complaint, wrapped pattern meets the WS-I
restrictions where soap:body should contain only one element as child
element.
14.9.5.2 Dis-Advantage
a) The WSDL became even more complicated.
Note: - If you want to build document/literal message format service, on the SEI
interface or at the implementation class, you need to mark with an annotation
@SOAPBinding (parameterStyle=SOAPBinding.ParameterStyle.BARE).
172
Mr. Sriman Web Services
SOAP
173
Mr. Sriman Web Services
15 SOAP
15.1 Introduction
SOAP 1.2 is the standard messaging protocol used by J2EE Web Services, and is
the de facto standard for Web services in general.
SOAP is just another XML markup language accompanied by rules that dictate its
use. SOAP has a clear purpose: exchanging data over networks. SOAP is a
network application protocol
174
Mr. Sriman Web Services
The Header element contains information about the message, in the form of one
or more distinct XML elements, each of which describes some aspect or quality of
service associated with the message.
175
Mr. Sriman Web Services
Modularity enables you to use different code libraries to process different parts of
a SOAP message.
176
Mr. Sriman Web Services
177
Mr. Sriman Web Services
Except in the case of fault messages, SOAP does not specify the contents of the
Body element (although it does specify the general structure of RPC-type
messages). As long as the Body contains well-formed XML, the application-
specific data can be anything. The Body element may contain any XML element or
it can be empty.
A SOAP message that contains a Fault element in the Body is called a fault
message.
When a fault message is generated, the Body of the SOAP message must contain
only a single Fault element and nothing else. The Fault element itself must
contain a faultcode element and a faultstring element, and optionally faultactor
and detail elements.
178
Mr. Sriman Web Services
179
Mr. Sriman Web Services
SOAP messages sent over HTTP are placed in the payload of an HTTP request or
response, an area that is normally occupied by form data and HTML
180
Mr. Sriman Web Services
Apache
Axis 2
181
Mr. Sriman Web Services
The Apache Axis 2 project is Java-based implementation of both the client and
server sides of the Web Service.
Axis2
| - bin – axis2.bat, axis2Server.bat, java2wsdl.bat, wsdl2java.bat and equivalent
.sh files
| - lib – Contains all Jar’s
| - repository
| - modules – modules.list, addressing-1.1.mar
| - services – services.list, version.aar
| - samples
| - webapp
| - config
| - axis2.xml
182
Mr. Sriman Web Services
a) Binary Distribution – Which contains Jar’s and tools that facilitate the
development of Web Service
b) War Distribution – Acts as server-side runtime engine in which your services
are deployed and exposed.
axis2-web
| - META-INF
| - WEB-INF
| - classes
| - conf – axis2.xml
| - lib – activation.jar, xmlschema.jar ….
| - modules – modules.lst, addressing.mar, soapmonitor.mar
| - services – services.lst, aservice.aar, version.aar….
| - web.xml
The main file in the above is axis2.xml which contains the entire configuration
related to message senders and receiver and their transport receivers etc. It
would also contain the information like which modules are active etc.
Below are the steps you need to follow in configuring the Apache axis 2.
a) Download or copy the axis binary and axis2.war distribution into your local
drive – You need to copy the axis2-1.6.1.zip and axis2.war that is being
distributed by apache axis2 into your local system -
http://apache.techartifact.com/mirror//axis/axis2/java/core/1.6.2/axis2-
1.6.2-war.zip
183
Mr. Sriman Web Services
184
Mr. Sriman Web Services
d) Now navigate into the extracted folder shown above, you will find axis2.war,
now extract the axis2.war into the axis2 folder as shown below.
185
Mr. Sriman Web Services
f) Now copy the axis2 folder (which we extracted from axis2-war.war) into the
above tomcat webapps directory
g) Now go to the command prompt navigate to the Tomcat directory bin and
start the tomcat server by running startup.bat as shown below.
186
Mr. Sriman Web Services
This will start the tomcat server in the new window after typing the startup.bat.
Note: - You need to set the JAVA_HOME environment variable before starting
the tomcat server.
Port Issues while starting tomcat server: - In few systems you might have
already been using the 8080 port. In such a case if you try to start the tomcat
server, it gives you an error 8080 port is already under use. In that case you
need to change the port of the tomcat server before starting the server as
shown below.
Go to Tomcat Directory/conf and locate the server.xml file. Open the server.xml
file and search for <connector> element whose protocol is “HTTP/1.1”. If you
look at the value there it is 8080, now change it to 8081, save the file and
restart the server. Now your tomcat runs under 8081 port.
h) Now open the browser and access the axis home page with
http://<adminhost>:<adminport>/axis2 will open the home page of the
Apache axis2. You can verify the correctness of your configuration in this
page.
187
Mr. Sriman Web Services
This completes the configuration of Apache Axis2 and allows you to proceed for
development of web service under this environment.
Rather Apache axis2 has come up with more consiged and easy deployment
model which is called “.aar” apache application archive. Once you finished
development of you Java classes, now you need to archive your application in to
.aar archive. The typical structure of this archive is as shown below.
<service-name>
| - <package> - containing classes of your service
| - lib – any jars that your code is dependent on. Axis2 related jars are not
required as the runtime already contains.
| - META-INF – it contains wsdl and services.xml
(services.xml is web service deployment descriptor)
Now you need to copy this archive into server-side runtime folder in tomcat
which is under tomcat\webapps\axis2\WEB-INF\services directory.
188
Mr. Sriman Web Services
189
Mr. Sriman Web Services
<wsdl:message name="orderResponse">
<wsdl:part element="et:orderConfirmation" name="return" />
</wsdl:message>
<wsdl:portType name="Buy">
<wsdl:operation name="order">
<wsdl:input message="tns:order" />
<wsdl:output message="tns:orderResponse" />
</wsdl:operation>
</wsdl:portType>
190
Mr. Sriman Web Services
Create a Java
Project
In the WSDL folder create the po.wsdl with the above wsdl document.
Create a folder WSDL
Copy all the axis2 jars into the lib directory of the
Project
Copy all the jars from c:\axis2-1.6.2\lib directory to the Project Lib directory and
configure the build path.
191
Mr. Sriman Web Services
Now switch to the project directory and run the wsdl2java.bat compiler which
will generates all the required classes for developing the service as shown here.
-R Where to generate the resource files like services.xml and wsdl. Generally
these files are placed under META-INF so the path has been specified as –
R src\META-INF
-d Stands for databinding. The possible values could be adb, xmlbeans, jibx
and jaxbri
-g Generate all the classes, it generates class for building both client and
server
192
Mr. Sriman Web Services
Now while exporting the project as Jar, you need to enter the archive name as
“.aar” extension. “.aar” stands for apache application archive, where axis2 reads
this special packing structure to deploy your application as service.
Export the project as jar
193
Mr. Sriman Web Services
Browse to Axis2 Homepage and click on services link you should see your service
being hosted.
Browse to Axis2 home page
194
Mr. Sriman Web Services
This completes the development steps of building Apache Axis2 based web
services using contract first approach.
<wsp:Policy wsu:Id="UsernameToken"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-
200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SupportingTokens
xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/Inclu
deToken/AlwaysToRecipient" />
</wsp:Policy>
</sp:SupportingTokens>
<ramp:RampartConfig
xmlns:ramp="http://ws.apache.org/rampart/policy">
<!-- <ramp:user>alice</ramp:user> -->
<ramp:passwordCallbackClass>org.amazon.sales.wsdl.sec.handler.PasswordCall
backHandler</ramp:passwordCallbackClass>
</ramp:RampartConfig>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
This should be added with in the service tag of services.xml indicating for which
service you want to apply the UserToken Security policy.
Along with that we need to write one more class PasswordCallbackHandler which is
declared in the above xml in <ramp:RampartConfig> tag.
195
Mr. Sriman Web Services
In this class we need to write the logic for validation the user/password credentials
that client has passed as part of Soap header.
PasswordCallbackHandler.java
package org.amazon.sales.wsdl.sec.handler;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
196
Mr. Sriman Web Services
197
Mr. Sriman Web Services
As we know for JAX-RPC or JAX-WS API we have various implementations like JAX-
RPC SI, Apache Axis, JAX-WS RI and Apache Axis2 etc. Along with that Oracle also
provided its own implementations for developing a JAX-RPC or JAX-WS API based
web services using Weblogic Server platform. This means, when you install
Weblogic Application Server, it will be shipped with all the Jar Implementations for
JAX-RPC and JAX-WS API, in addition it provides tools for supporting the
development of Web Service in Oracle Weblogic Server.
Instead of developer working directly with the Weblogic server shipped tools,
Oracle has provided a convineint integrated development environment Oracle
JDeveloper which allows you to build web services sophisticated.
Oracle JDeveloper along with supporting various application development types like
Java, Web applications, Distributed EJB applications, SOA, it provides an GUI
Wizard’s which allows you to navigate between wizards by clicking on next to
create/generate Webservices. Oracle JDeveloper not only supports development of
Provider, it even provides GUI Wizard for developing Consumer’s as well.
Before proceeding further let us try to understand how to setup the environment.
It is the Universal Installer which can be installed on any platform. To install and
run the Jdeveloper we need minimum JDK 1.6. One you double click on the Jar,
it takes couple of minutes to open the Installation wizard. You just need to
walkthrough the wizards by clicking on next.
In the second screen it will ask you to choose the Middleware Home directory.
198
Mr. Sriman Web Services
Select the create a new Middleware Home and leave it to the default path and
continue the installation by clicking on next.
In the Screen# - 3 it will ask for type of installation here, you need to select as
complete. By selecting complete, along with installing Oracle JDeveloper, it even
installs Oracle Weblogic server for deploying you applications.
199
Mr. Sriman Web Services
In the Screen# - 4 it will ask for the JDK path, provide the directory path under
which your Java has been installed, and click on next.
In the Screen# - 5 it will display the directories under which JDeveloper and
Weblogic server is being installed.
Finally click on next and next to complete installation. Now open the Oracle
Jdeveloper by clicking on the Start menu.
This will pulls up the Oracle JDeveloper on the desktop, which contains the
Integrated Weblogic Server in it. If it is the first time we are running the Oracle
Weblogic Server, when we click on start Server Instance from Run menu it will
ask you the Port, Username and password with which you want to configure the
default domain on the Weblogic server as shown below.
200
Mr. Sriman Web Services
Now when you click on the Start Server Instance, it will popup a dialog window
and ask you to enter the port, username and password to configure the domain.
From the next run onwards, it will not prompt again.
201
Mr. Sriman Web Services
Click on File menu, select New will opens a dialog window. Select here the
Application type as generic application with a name and click on next as
shown below.
202
Mr. Sriman Web Services
After clicking on the Next, it will show a Project Dialog wizard. Here you
need to give the Project Name and select the type of technologies you
want to use in building the project and click on Next.
203
Mr. Sriman Web Services
In this you need enter the Default Package you want to use as part of
your project and click on Finish.
Default Package
204
Mr. Sriman Web Services
After creating the Application & Project, you need to right click on the
Project and select new Java class. Write a class with some methods which
you want to expose as Web Service. You don’t need to mark with any
Create a Pojo class annotations and let it be absolutely a Pojo class as shown below.
Give some name to the Java class as ProductInfo. Declare some methods
you want to expose as web service methods as shown below.
205
Mr. Sriman Web Services
Now right click on the ProductInfo.java file shown in the Projects window
left. Click on the menu item create WebService.
Expose as Webservice
206
Mr. Sriman Web Services
After click on Create Web Service option, it opens a wizard dialogue where
it will take you through set of screens in creating the Web Service.
Dialogue# - 1
You need to select which type of service you want to build JAX-RPC or
JAX-WS RI or WLS based JAX-WS service.
Navigate thorough wizard to create service
207
Mr. Sriman Web Services
You can add an SEI interface and configure the Service Name etc.
Dialogue# - 2
208
Mr. Sriman Web Services
You can select the existing interface as SEI interface or can decide to
generate one by default.
Dialogue# - 3
209
Mr. Sriman Web Services
Here you need to choose the Message Format whether it is SOAP 1.1 or
SOAP 1.2 based service
Dialogue# - 4
210
Mr. Sriman Web Services
You need to select the methods you want to expose as Web service
methods in your class.
Dialogue # - 5
Dialogue# - 6:- Let you choose the classes for whom you want to generate
Dialogue # 6,7 and 8
binding classes.
Dialogue# - 7:- Ask you to configure the security policies. We will leave it
to default by selecting No Policies.
211
Mr. Sriman Web Services
Now goto run menu and select start server instance. It will start the
Weblogic Server. Wait until begins running.
212
Mr. Sriman Web Services
Once the Server Instance is running. You need to right click on the Project
from the left projects pane. Select the deploy and deploy the project onto
Integrated Weblogic Server Instance.
Deploy the Project
213
Mr. Sriman Web Services
Now open the Web browser and access the Admin console of Weblogic
Server
214
Mr. Sriman Web Services
Expand the (+) sign on the application and click on ProductInfoService will
opens a dialogue window. Click on Testing tab will open the below dialogue
window.
Expand the application and select test client
Now click on Test client link will open a test dialogue window.
Test Client
This completes the development and testing of Oracle Weblogic Server based
Web services through Oracle JDeveloper development IDE.
215
Mr. Sriman Web Services
Apache
CXF
216
Mr. Sriman Web Services
c) Little amount of code is being generated when compared with other frameworks.
f) CXF supports variety of Web Service Standards including SOAP, the WS-I Basic
profile, WSDL, WS-Addressing, WS-Security (WSSE), WS-Policy, WS-
ReliableMessaging, WS-SecurityPolicy, WS-SecureConversation, WS-Trust etc.
http://cxf.apache.org/download.html
As we mentioned the current release is 2.7.6. We are using in this examples the
2.6.9 version.
Once you download the binary zip distribution apache-cxf-2.6.9.zip, copy it to the
c:\drive and extract it.
217
Mr. Sriman Web Services
apache-cxf-2.6.9
| - bin - Contains all the tools wsdl2java.bat, java2wsdl.bat,
wsdlvalidator.bat etc
| - docs – java docs
| - etc
| - lib - All the jars
| - modules
| - samples – all the samples of apache cxf
You have completed setting up the tools/environment; to build apache cxf based
web services.
Now we are trying to develop JAX-WS API, Apache CXF implementation based
provider using Servlet endpoint, using Contract First approach, using Sync Req-
Reply based provider using document-literal based web service.
Let us consider the below traininfo.wsdl document for developing the service.
218
Mr. Sriman Web Services
traininfo.wsdl
219
Mr. Sriman Web Services
<wsdl:message name="reserve">
<wsdl:part element="it:ReservationInfo" name="in" />
</wsdl:message>
<wsdl:message name="reserveResponse">
<wsdl:part element="it:Ticket" name="out" />
</wsdl:message>
<wsdl:portType name="TrainInfo">
<wsdl:operation name="reserve">
<wsdl:input message="tns:reserve" />
<wsdl:output message="tns:reserveResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="TrainInfoSOAPBinding" type="tns:TrainInfo">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="reserve">
<soap:operation
soapAction="http://irctc.co.in/reservation/wsdl#reserve" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="TrainInfoService">
<wsdl:port binding="tns:TrainInfoSOAPBinding"
name="TrainInfoSOAPPort">
<soap:address location="http://www.example.org/" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
220
Create a Dynamic Web Project
221
Mr. Sriman
Web Services
Create WSDL document under WEB-INF directory Configure Target runtime
222
(while creating project)
Mr. Sriman
Web Services
Copy all the Apache CXF Jar’s from Dev Env to Project lib
223
directory
Mr. Sriman
Web Services
Mr. Sriman Web Services
As it is contract first appraoch, once we are done with writing the WSDL
document, we need to generate binding classes, to generate binding
classes from WSDL, we need to run WSDL2Java tool that is provided by
Apache CXF.
224
Mr. Sriman Web Services
at client side.
225
Mr. Sriman Web Services
226
Import two additional xml files provided by Give the name of the file as cxf-services.xml and import
227
cxf the jaxws namespace
Mr. Sriman
Web Services
Mr. Sriman Web Services
jaxws:endpoint bean
Configure web.xml
1) Configure ContextLoaderListener which will takes the cxf-
services.xml as input to expose your jaxws endpoint as bean
2) Configure CXFServlet which will acts as an servlet endpoint in
processing the request and dispatching the response as shown
below.
Configure Web.xml
228
Deploy your project and start server
229
Mr. Sriman
Web Services
Test service using SOAP Test by accessing the wsdl url
230
UI
Mr. Sriman
Web Services
Mr. Sriman Web Services
231
Mr. Sriman Web Services
232
Mr. Sriman Web Services
Open the command prompt and configure the path pointing to the directory
where wsdl2java tool is there.
Run the wsdl2java tool to generate the client side classes
Refresh the project and create one more class TrainInfoClient bean, into
Create a Client class in the project
233
Mr. Sriman Web Services
Configure classes as beans Configure TrainInfoClient also as bean and inject TrainInfo consumer
endpoint as dependent via setter injection.
Create a Test class and run
234
Mr. Sriman Web Services
JAX-RS
235
Mr. Sriman Web Services
REST architecture has been higly influenced from web architecture, Roy Fielding one of
the principal authors of HTTP specification and co-founder of the Apache HTTP Server
project, as part of his doctrial thesis has defined several architectural principles that
defines the REST.
20.1 Principles
1) Addressable resource: Every resource has to have a unique directly
addressable URI so that we can reach directly. To make integration efforts much
easy it is very important to have a direct reachable address. If you see in an Jee
most of the distributed applications will not have direct addressable URI, like Ejb
or Web Services, due to which other applications has to understand the specific
access techniques to integrate.
a. GET: GET is a readonly operation. It is used for query the server for some
information. It is safe and idempotent method.
d. HEAD: It is exactly like GET except that instead of returning the response
body.
236
Mr. Sriman Web Services
Familiarity: If you have an URI to access the resource, you know which
methods are exactly there on that resource. You don’t need an IDL or WSDL to
know the information about the service.
Scalability: As the operations are fixed, we can predict the behavior of those
methods, let’s say a GET always returns the information of the resource, it never
modifies the resource. This indicates if we access the resource and for the next
access to the resource if there is not PUT or POST or DELETE requests inbetween
we don’t need to send the request to the server rather we can cache and return
the information from client.
If your service is being built on above principles then it is called RESTful Resource.
237
Mr. Sriman Web Services
20.2 Architecture
Restful resource architecture is different from a normal web service architecture.
Below is the diagram depicting the same.
JAX-RS API has been designed completely based on http protocol. So we cannot
built REST Resources on any other protocol apart from Http. To exchange the
data between consumer and provider in case of Webservice we need to use only
XML, in case of REST in addition to XML we can use any other data formats as
well like JSON or TEXT or HTML. Most people use JSON as alternate format to
XML to easily parse the data. SOAP is completely eliminated as it is an extra
overhead over the XML. To describe the information about provider in case of
web service we have WSDL, but in case of REST there is no service description
language, as there is not description, there is no registry and publish and
suscribe. In case of REST the consumer can be any consumer who can send Http
request with data format that is requested by the provider. He need not be a
special program built on standards like web service.
As you have seen lot of things are changed between web service and REST, that
is the reason it is also called as new architectural style of developing web
services is called REST.
As part of this we are going to see examples on how to work with Jersey as well
as RestEasy.
238
Mr. Sriman Web Services
Now extract the RestEasy binary distribution zip downloaded. It contains a lib and
two more zip files as shown below.
The lib directory contains generic jar’s that should be used to develop RestEasy
services that can be deployed on any app server. But the other two zip’s contains
jars one for Jboss and other for Wildfly servers resp.
As we are deploying on Jboss we need to use Jboss related jars. Now copy the zip
and goto JBoss AS 7.1 modules directory. For e.g..
<JBOSS_HOME_DIR>\modules and page the zip.
Right click on the zip and extract to here. It will ask you to replace some of the
existing jar’s just say “yes” will completes copying all the RestEasy jars into the
JBoss application server.
239
Mr. Sriman Web Services
240
Mr. Sriman Web Services
Annotate the class with JAX-RS annotation to make this as Resource class.
Configure web.xml
241
Mr. Sriman Web Services
242
Mr. Sriman Web Services
20.7.1 RestEasy
If you observe in case of RestEasy we wrote the url-pattern as /*, but /* is not
recommended url-pattern. To customize this we need to write one more init-
parameter as shown below
243
Mr. Sriman Web Services
<servlet>
<servlet-name>resteasy</servlet-name>
<servlet-
class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-
class>
<init-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>resteasy</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
20.7.2 Jersey
In case of jersey, we configured one init-param, instead of
“jersey.config.server.provider.packages” we can give classes also as input as
shown below.
<servlet>
<servlet-name>jersey</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-
class>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-
name>
<param-value>com.fj.resource.PersonResource</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
244
Mr. Sriman Web Services
If we return Resource object then the scope of the resource will become
singleton. Only one object of that resource will be used to process any number
of requests. If we return class reference in getClasses() method then for every
request new object of the resource will be created.
package com.fj.app;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import com.fj.resource.PersonResource;
@ApplicationPath("/rest")
public class FirstApplication extends Application {
private Set<Object> singletons;
public FirstJerseyApplication() {
singletons = new HashSet<Object>();
singletons.add(new PersonResource());
}
@Override
public Set<Object> getSingletons() {
return singletons;
}
package com.bhm.dto;
import java.io.Serializable;
public class ParcelInfo implements Serializable {
private int awbNo;
private String src;
private String dest;
private String descr;
private String status;
245
Mr. Sriman Web Services
package com.bhm.resource;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.StreamingOutput;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import com.bhm.dto.ParcelInfo;
@Path("/bluedart")
public class BluedartCourierResource {
private Map<Integer, ParcelInfo> parcelDataMap;
private AtomicInteger index;
public BluedartCourierResource() {
parcelDataMap = new HashMap<Integer, ParcelInfo>();
index = new AtomicInteger(0);
}
@POST
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.TEXT_PLAIN)
public int createParcel(InputStream is) {
ParcelInfo parcelInfo = null;
int awbNo = 0;
246
Mr. Sriman Web Services
try {
parcelInfo = buildParcelInfo(is);
awbNo = index.incrementAndGet();
parcelInfo.setAwbNo(awbNo);
parcelInfo.setStatus("New");
parcelDataMap.put(awbNo, parcelInfo);
} catch (Exception e) {
e.printStackTrace();
}
return awbNo;
}
@GET
@Produces(MediaType.APPLICATION_XML)
public StreamingOutput getParcelInfo(@QueryParam("awbNo") int awbNo)
{
ParcelInfo parcelInfo = null;
String xml = null;
parcelInfo = parcelDataMap.get(awbNo);
if (parcelInfo != null) {
xml = convert(parcelInfo);
}
return new ParcelInfoWriter(xml);
}
@Override
public void write(OutputStream out) throws IOException,
WebApplicationException {
PrintWriter writer = null;
247
Mr. Sriman Web Services
factory = DocumentBuilderFactory.newInstance();
builder = factory.newDocumentBuilder();
doc = builder.parse(is);
if (doc != null) {
parcelInfo = new ParcelInfo();
root = doc.getFirstChild();
children = root.getChildNodes();
.setAwbNo(Integer.parseInt(child.getTextContent()));
} else if (child.getNodeName().equals("src")) {
parcelInfo.setSrc(child.getTextContent());
} else if (child.getNodeName().equals("dest")) {
parcelInfo.setDest(child.getTextContent());
} else if (child.getNodeName().equals("descr")) {
parcelInfo.setDescr(child.getTextContent());
} else if (child.getNodeName().equals("status")) {
parcelInfo.setStatus(child.getTextContent());
}
}
}
return parcelInfo;
}
Now you can register the resource either using Servlet approach or using
Application class to test it.
248
Mr. Sriman Web Services
.append(parcelInfo.getAwbNo()).append("</awbNo>");
buffer.append("<src>").append(parcelInfo.getSrc()).append("</src>");
buffer.append("<dest>").append(parcelInfo.getDest()).append("</dest>"
);
buffer.append("<descr>").append(parcelInfo.getDescr())
.append("</descr>");
buffer.append("<status>").append(parcelInfo.getStatus())
.append("</status>").append("</parcelInfo>");
return buffer.toString();
}
249
Mr. Sriman Web Services
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.PathSegment;
@Path("/passport/{passportNo}")
public class PassportResource {
/** You can use @PathParam at the attribute level **/
/* @PathParam("passportNo") */
/* private String passportNo; */
/*
* You can use @PathParam at constructor level
* public PassportResource(@PathParam("passportNo") String passportNo) {
* this.passportNo = passportNo; }
*/
250
Mr. Sriman Web Services
package com.rsi.matrix.resource;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.PathSegment;
@Path("/car")
public class CarResource {
matrixParamMap = makeSeg.getMatrixParameters();
for (String key : matrixParamMap.keySet()) {
buffer.append(key);
for (String val : matrixParamMap.get(key)) {
buffer.append("," + val);
}
buffer.append("model : ").append(modelSeg.getPath())
.append("matrix parameters : ");
matrixParamMap = modelSeg.getMatrixParameters();
for (String key : matrixParamMap.keySet()) {
buffer.append(key);
for (String val : matrixParamMap.get(key)) {
buffer.append("," + val);
}
251
Mr. Sriman Web Services
return buffer.toString();
}
package com.rsi.headerparam.resource;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.ws.rs.Consumes;
import javax.ws.rs.CookieParam;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
@Path("/courier")
public class CourierResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getAgentName(@HeaderParam("agentId") String agentId) {
return "Agent id : " + agentId + " name : apparao";
}
252
Mr. Sriman Web Services
@POST
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.TEXT_PLAIN)
public String send(InputStream is,
@HeaderParam("courier-agent-id") String courierAgentId) {
StringBuffer buffer = null;
int c = 0;
import javax.ws.rs.Consumes;
import javax.ws.rs.CookieParam;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/courier")
public class CourierResource {
@GET
@Path("/status")
@Produces(MediaType.TEXT_PLAIN)
public String getCourierStatus(@CookieParam("agentId") String agentId,
@QueryParam("trackingId") String trackingId) {
return "Agent : " + agentId + " trackingId : " + trackingId
+ " is in progress...";
}
}
253
Mr. Sriman Web Services
package com.rsi.formparam.resource;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/emp")
public class EmpResource {
@POST
@Produces(MediaType.TEXT_PLAIN)
public String insert(@FormParam("id") int id, @FormParam("name")
String name) {
return "Inserted id : " + id + " name : " + name + "
successfully...";
}
}
254
Mr. Sriman Web Services
package com.rsi.progheaders.resource;
import java.util.List;
import java.util.Map;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
@Path("/header")
public class HeaderResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getAllHeaders(@Context HttpHeaders headers) {
StringBuffer buffer = null;
MultivaluedMap<String, String> headerMap = null;
Map<String, Cookie> cookieMap = null;
return buffer.toString();
}
}
255
Mr. Sriman Web Services
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
@Path("/uri")
public class URIResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getUriInformation(@Context UriInfo uri) {
StringBuffer buffer = null;
MultivaluedMap<String, String> queryMap = null;
1) Any java primitive types can be taken as candidates for resource injection
2) It can be any class type as well, but the class should have the following
a. One single string argument constructor
b. A valueOf method which takes Object type and convert to string
3) It can be a List or Set or SortedSet as a parameter where whose generic types
shoud fall under the above two categories.
256
Mr. Sriman Web Services
package com.rsi.autoparamconv.resource;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
@Path("/address")
public class AddressResource {
@Path("/zip/{zip}")
@Produces(MediaType.TEXT_PLAIN)
@GET
public String getAreaCode(@PathParam("zip") int zip) {
return "zip : " + zip;
}
@GET
@Path("/area/{areaCode}")
@Produces(MediaType.TEXT_PLAIN)
public String findZipCodes(@PathParam("areaCode") SearchCriteria criteria) {
return "Zip for areaCode : " + criteria.getAreaCode();
}
@GET
@Path("/blacklist")
@Produces(MediaType.TEXT_PLAIN)
public String addToBlackList(@QueryParam("zip") List<Integer> zipCodes) {
StringBuffer buffer = null;
257
Mr. Sriman Web Services
package com.rsi.autoparamconv.resource;
package com.rsi.beanparam.resource;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.QueryParam;
258
Mr. Sriman Web Services
package com.rsi.beanparam.resource;
import javax.ws.rs.BeanParam;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/store")
public class StoreResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String search(@BeanParam Criteria criteria) {
return "itemCode : " + criteria.getItemCode() + ", category : "
+ criteria.getCategory() + ", manufacturer : "
+ criteria.getManufacturer() + ", price : "
+ criteria.getPrice();
}
}
package com.cpc.dto;
259
Mr. Sriman Web Services
package com.cpc.resource;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import com.cpc.dto.OrderInfo;
@Path("/pizza")
public class PizzaStore {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String placeOrder(
@QueryParam("size") @DefaultValue("SMALL") OrderInfo
orderInfo) {
return "You order for " + orderInfo.getSize()
+ " inch pizza is under processing...";
}
}
package com.cpc.converters;
import javax.ws.rs.ext.ParamConverter;
import com.cpc.dto.OrderInfo;
@Override
public OrderInfo fromString(String val) {
OrderInfo orderInfo = null;
260
Mr. Sriman Web Services
@Override
public String toString(OrderInfo orderInfo) {
String val = null;
if (orderInfo != null) {
if (orderInfo.getSize() == 8) {
val = "SMALL";
} else if (orderInfo.getSize() == 12) {
val = "MEDIUM";
} else if (orderInfo.getSize() == 16) {
val = "LARGE";
}
}
return val;
}
package com.cpc.converters;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import javax.ws.rs.ext.Provider;
import com.cpc.dto.OrderInfo;
@Provider
public class PizzaStoreParamConverterProvider implements ParamConverterProvider {
@Override
public <T> ParamConverter<T> getConverter(Class<T> genericType,
Type rawType, Annotation[] annotations) {
System.out.println("Generic Type : " + genericType.getName());
System.out.println("rawType : " + rawType.getClass().getName());
System.out.println("annotations : ");
for (Annotation annon : annotations) {
System.out.println(annon.toString());
}
if (genericType.isAssignableFrom(OrderInfo.class)) {
return (ParamConverter<T>) new OrderInfoParamConverter();
}
return null;
}
261
Mr. Sriman Web Services
import javax.inject.Inject;
import javax.ws.rs.Path;
@Path("/courier")
public class CourierResource {
/**
* Sub-Resource locator method
* @return
*/
@Path("/customerservice")
// sub-resource method
public CustomerServiceResource track() {
return new CustomerServiceResource();
}
package com.srl.resource;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getCourierStatus(@QueryParam("awbNo") String awbNo) {
return "Awb no : " + awbNo + " is ready for delivery";
}
}
262
Mr. Sriman Web Services
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@Path("/payment")
public class PaymentResource {
/**
* Dynamic Dispatching
* @param type
* @return
*/
@Path("/{type}/{gateWay}")
public Object process(@PathParam("type") String type) {
Object subResource = null;
if (type.equals("creditcard")) {
subResource = new CreditCardPaymentResource();
} else if (type.equals("debitcard")) {
subResource = new DebitCardPaymentResource();
}
return subResource;
}
}
package com.srl.resource;
import javax.ws.rs.GET;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String processPayment(@QueryParam("cardNo") String cardNo,
@PathParam("gateWay") String gateWay) {
return "Processed payment with cardNo : " + cardNo + " gateWay : "
+ gateWay;
}
}
263
Mr. Sriman Web Services
package com.srl.resource;
import javax.ws.rs.GET;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String processDebit(@QueryParam("cardNo") String cardNo,
@QueryParam("pin") String pin, @PathParam("gateWay") String
gateWay) {
return "Processed payment with cardNo : " + cardNo + " pin : " + pin
+ " gateWay : " + gateWay;
}
}
package com.ch.resource;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
@Path("/aadhar")
public class AadharRegistration {
@POST
@Consumes(MediaType.TEXT_PLAIN)
264
Mr. Sriman Web Services
@Produces(MediaType.TEXT_PLAIN)
@Path("/inputstream")
public String register(InputStream inputstream) throws IOException {
int c = 0;
StringBuffer buffer = null;
BufferedInputStream bis = null;
@POST
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.TEXT_PLAIN)
@Path("/reader")
public String register(Reader reader) throws IOException {
String line = null;
BufferedReader br = null;
StringBuffer buffer = null;
@Path("/byte")
@POST
@Produces(MediaType.TEXT_PLAIN)
@Consumes(MediaType.TEXT_PLAIN)
public String register(byte[] body) {
StringBuffer buffer = null;
265
Mr. Sriman Web Services
266
Mr. Sriman Web Services
To send the file as input to the above resource we need to use the below jsp
Uploadfile.jsp
The problem is not only the code duplication across all the Resources, even the
Resources will be coupled with data format. Instead we can use Custom content
handler which will convert the raw data into a specific data format.
So, we need to write One content handler which converts input data into Object
(MessageBodyReader) and we need to write one more content handler which converts
Object back to raw data (MessageBodyWriter).
267
Mr. Sriman Web Services
package com.csvch.common;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface CSVType {
package com.csvch.dto;
import com.csvch.common.CSVType;
@CSVType
public class Fare {
private String billNo;
private String distance;
//setter & getters
}
package com.csvch.dto;
import com.csvch.common.CSVType;
@CSVType
public class TripInfo {
private String src;
private String dest;
// setters & getters
}
268
Mr. Sriman Web Services
package com.csvch.readers;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import javax.ws.rs.Consumes;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
import com.csvch.common.CSVType;
@Provider
@Consumes(MediaType.TEXT_PLAIN)
public class CSVMessageBodyReader implements MessageBodyReader<Object> {
private final static String DELIMETER = ",";
@Override
public boolean isReadable(Class<?> genericType, Type rawType,
Annotation[] annotations, MediaType mediaType) {
if (genericType.isAnnotationPresent(CSVType.class)) {
return true;
}
return false;
}
@Override
public Object readFrom(Class<Object> genericType, Type rawType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> requestHeaderMap,
InputStream inputStream) throws IOException,
WebApplicationException {
Object obj = null;
String data = null;
Map<String, String> dataMap = null;
try {
data = extractData(inputStream);
dataMap = convertToMap(data);
obj = bind(genericType, dataMap);
} catch (Exception e) {
e.printStackTrace();
269
Mr. Sriman Web Services
return obj;
}
try {
buffer = new StringBuffer();
bis = new BufferedInputStream(inputStream);
while ((c = bis.read()) != -1) {
buffer.append((char) c);
}
} finally {
bis.close();
inputStream.close();
}
return buffer.toString();
}
obj = classType.newInstance();
for (String attrNm : dataMap.keySet()) {
attrVal = dataMap.get(attrNm);
270
Mr. Sriman Web Services
return obj;
}
methods = classType.getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equalsIgnoreCase("set" + attrNm)) {
method.invoke(obj, attrVal);
break;
}
}
}
}
package com.csvch.resource;
import java.util.UUID;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.csvch.dto.Fare;
import com.csvch.dto.TripInfo;
@Path("/taxi")
public class TaxiService {
@POST
@Produces(MediaType.TEXT_PLAIN)
@Consumes(MediaType.TEXT_PLAIN)
public Fare hire(TripInfo tripInfo) {
Fare fare = null;
return fare;
}
}
271
Mr. Sriman Web Services
package com.csvch.writers;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import com.csvch.common.CSVType;
@Provider
@Produces(MediaType.TEXT_PLAIN)
public class CSVMessageBodyWriter implements MessageBodyWriter<Object> {
@Override
public long getSize(Object object, Class<?> genericType, Type rawType,
Annotation[] annotations, MediaType mediaType) {
return -1;
}
@Override
public boolean isWriteable(Class<?> genericType, Type rawType,
Annotation[] annotations, MediaType mediaType) {
if (genericType.isAnnotationPresent(CSVType.class)) {
return true;
}
return false;
}
@Override
public void writeTo(Object object, Class<?> genericType, Type rawType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> responseHeaderMap,
OutputStream outputstream) throws IOException,
WebApplicationException {
PrintWriter writer = null;
String csv = null;
try {
csv = convertToCSV(genericType, object);
writer = new PrintWriter(outputstream);
writer.print(csv);
} catch (Exception e) {
272
Mr. Sriman Web Services
e.printStackTrace();
throw new WebApplicationException(e);
} finally {
writer.close();
}
buffer.append(f.getName()).append("=").append(f.get(object));
} else {
buffer.append(",").append(f.getName()).append("=")
.append(f.get(object));
}
}
return buffer.toString();
}
273
Mr. Sriman Web Services
package com.cr.dto;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlType
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "cardUpgradeInfo")
public class CardUpgradeInfo {
private String cardNo;
private int month;
private int year;
private String name;
package com.cr.dto;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlType
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "personelInfo")
public class PersonelInfo {
private String name;
private int age;
private int ssn;
274
Mr. Sriman Web Services
package com.cr.dto;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlType
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "reqStatus")
public class ServiceRequestStatus {
private String cardNo;
private String msg;
private String status;
package com.cr.resource;
import java.net.URI;
import java.net.URISyntaxException;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import com.cr.dto.CardUpgradeInfo;
import com.cr.dto.PersonelInfo;
import com.cr.dto.ServiceRequestStatus;
@Path("/bank")
public class BankResource {
@GET
@Path("/bal/{accno}")
@Produces(MediaType.TEXT_PLAIN)
public Response getBalance(@PathParam("accno") String accno) {
Response response = null;
ResponseBuilder builder = null;
275
Mr. Sriman Web Services
return response;
}
@POST
@Path("/checkbookreq/{accno}")
public Response requestCheckbook(@PathParam("accno") String accno) {
Response response = null;
ResponseBuilder builder = null;
@PUT
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
public Response upgradeCard(CardUpgradeInfo cardUpgradeInfo) {
Response response = null;
ResponseBuilder builder = null;
ServiceRequestStatus status = null;
builder = Response.ok();
builder = builder.header("serviceRequestNumber", "SR31414");
builder = builder.entity(status);
response = builder.build();
return response;
}
@POST
@Path("/apply")
@Consumes(MediaType.APPLICATION_XML)
public Response applyCreditCard(PersonelInfo pInfo)
throws URISyntaxException {
NewCookie cookie = null;
276
Mr. Sriman Web Services
But in case if we want to return a custom error response rather than a default error
response message we need to handle the exception and should return as a response
shown below.
package com.em.dto;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlType
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "customer")
public class Customer {
private int id;
private String name;
package com.em.exception;
277
Mr. Sriman Web Services
package com.em.exception.mapper;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import com.em.exception.CustomerNotFoundException;
@Provider
public class CustomerNotFoundExceptionMapper implements
ExceptionMapper<CustomerNotFoundException> {
@Override
public Response toResponse(CustomerNotFoundException ex) {
return Response.status(Status.BAD_REQUEST).entity(ex.getMessage())
.build();
}
}
package com.em.resource;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.PostConstruct;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import com.em.dto.Customer;
import com.em.exception.CustomerNotFoundException;
@Path("/customer")
public class CustomerResource {
private Map<Integer, Customer> dbMap;
private AtomicInteger customerindex;
public CustomerResource() {
dbMap = new ConcurrentHashMap<Integer, Customer>();
customerindex = new AtomicInteger(0);
278
Mr. Sriman Web Services
@POST
@Consumes(MediaType.APPLICATION_XML)
public Response createCustomer(Customer customer) throws
URISyntaxException {
String baseUri = null;
int id = 0;
baseUri = "/customer/";
id = customerindex.incrementAndGet();
baseUri += id;
customer.setId(id);
dbMap.put(id, customer);
return Response.created(new URI(baseUri)).build();
}
@PUT
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.TEXT_PLAIN)
public Response updateCustomer(Customer customer)
throws CustomerNotFoundException {
if (dbMap.containsKey(customer.getId()) == false) {
throw new CustomerNotFoundException(
"Customer is not found to update...");
}
dbMap.put(customer.getId(), customer);
return Response.ok("Customer updated").build();
}
@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_XML)
public Response getCustomer(@PathParam("id") int customerId)
throws CustomerNotFoundException {
if (dbMap.containsKey(customerId) == false) {
throw new CustomerNotFoundException("Customer Id is invalid");
}
return Response.ok().entity(dbMap.get(customerId)).build();
}
}
279
Mr. Sriman Web Services
package com.firstrs.resource.client;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
builder = ClientBuilder.newBuilder();
builder.property("connection.timeout", 1000 * 60);
client = builder.build();
target = client.target("http://localhost:8081/FirstJbossRSWeb/greet");
target = target.queryParam("person", "john");
}
}
package com.rsinjection.resource.pathparam.client;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
280
Mr. Sriman Web Services
client = ClientBuilder.newClient();
target = client.target(RESOURCE_URI).path("/{make}");
target = target.resolveTemplate("make", "Maruthi").matrixParam("year",
"2014");
target = target.path("/{model}").resolveTemplate("model", "Swift")
.matrixParam("color", "red");
System.out.println(target.getUri().getPath());
String data = target.request().get(String.class);
System.out.println(data);
}
}
package com.rsinjection.resource.pathparam.client;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
try {
client = ClientBuilder.newClient();
target = client.target(RESOURCE_URI);
281
Mr. Sriman Web Services
package com.rsinjection.resource.pathparam.client;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
client = ClientBuilder.newClient();
client.property("connection.timeout", 1000 * 60);
target = client.target(RESOURCE_URI);
target = target.path("/getPassportNo/{firstname}-{lastname}");
282
Mr. Sriman Web Services
package com.cch.resource.client;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
client = ClientBuilder.newClient();
client.register(CSVMessageBodyReader.class);
client.register(CSVMessageBodyWriter.class);
target = client.target(RESOURCE_URI);
283
Mr. Sriman Web Services
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
package com.wia.resource;
import javax.ws.rs.Path;
@Path("/absorder")
public class AbstractOrderImpl extends AbstractOrder {
@Override
String getOrderStatus(int orderNo) {
return "Status : pending ... for order : " + orderNo;
}
package com.wia.resource;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
@Path("/order")
public interface Order {
@GET
@Produces(MediaType.TEXT_PLAIN)
String getOrderStatus(@QueryParam("orderNo") int orderNo);
}
package com.wia.resource;
@Override
public String getOrderStatus(int orderNo) {
return "Order No : " + orderNo + " is in processing...";
}
284
Mr. Sriman Web Services
285
Mr. Sriman Web Services
package com.async.resource.client;
import java.util.concurrent.ExecutionException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.InvocationCallback;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
client = ClientBuilder.newClient();
target = client.target(RESOURCE_URI);
target = target.queryParam("stocknm", "icicbank");
target.request().async().get(new ResponseCallback());
/*
* System.out.println("control released");
*
* Response response = future.get();
* System.out.println("response collected"); if (response.getStatus() ==
* 200) { String data = response.readEntity(String.class);
* System.out.println(data); }
*/
System.out.println("main method ended...");
}
@Override
public void completed(Response response) {
String data = response.readEntity(String.class);
System.out.println(data);
}
@Override
public void failed(Throwable ex) {
}
}
286
Mr. Sriman Web Services
20.18 Caching
package com.cw.resource;
import java.util.Calendar;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("/pnr")
public class PNRStatusResource {
@GET
@Path("/{pnr}")
@Produces(MediaType.TEXT_PLAIN)
public Response getPnrStatus(@PathParam("pnr") String pnr) {
Response response = null;
Calendar timestamp = null;
timestamp = Calendar.getInstance();
timestamp.set(2014, 7, 18, 9, 0, 0);
return response;
}
package com.cw.resource;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("/stock")
public class StockQuoteResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("/{stocknm}")
public Response getStockPrice(@PathParam("stocknm") String stocknm) {
Response response = null;
287
Mr. Sriman Web Services
CacheControl cc = null;
cc = new CacheControl();
cc.setPrivate(true);
cc.setMaxAge(20009200);
System.out.println("Request is processing...");
response = Response.ok("stock nm : " + stocknm + " price : 2422")
.cacheControl(cc).build();
return response;
}
package com.cw.dto;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlType
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "stockInfo")
public class StockInfo {
private String name;
private double price;
private String org;
288
Mr. Sriman Web Services
package com.cw.resource;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.EntityTag;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import com.cw.dto.StockInfo;
@Path("/stockinfo")
public class StockResource {
private Map<String, StockInfo> dbMap;
public StockResource() {
dbMap = new ConcurrentHashMap<String, StockInfo>();
}
@POST
@Consumes(MediaType.APPLICATION_XML)
public Response newStock(StockInfo si) throws URISyntaxException {
dbMap.put(si.getName(), si);
return Response.created(new URI("/stockinfo/" + si.getName())).build();
}
@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Path("/{stocknm}")
public Response getStock(@PathParam("stocknm") String stocknm,
@Context Request request) {
ResponseBuilder builder = null;
StockInfo si = null;
CacheControl cc = null;
EntityTag eTag = null;
if (dbMap.containsKey(stocknm) == false) {
throw new NotFoundException("Stock doesn't exists");
289
Mr. Sriman Web Services
// sever object
si = dbMap.get(stocknm);
eTag = new EntityTag(String.valueOf(si.hashCode()));
builder = request.evaluatePreconditions(eTag);
if (builder != null) {// pick the data from cache
// send redirect request
return builder.build();
}
cc = new CacheControl();
cc.setMustRevalidate(true);
cc.setMaxAge(1000 * 60 * 60);
cc.setPrivate(true);
return Response.ok(si).cacheControl(cc).tag(eTag).build();
}
@PUT
@Consumes(MediaType.APPLICATION_XML)
public Response updateStock(StockInfo si, @Context Request request) {
ResponseBuilder builder = null;
EntityTag etag = null;
StockInfo ssi = null;
if (dbMap.containsKey(si.getName()) == false) {
throw new NotFoundException("Stock doesn't exists for updating");
}
ssi = dbMap.get(si.getName());
etag = new EntityTag(String.valueOf(ssi.hashCode()));
builder = request.evaluatePreconditions(etag);
if (builder != null) {
// pre-conditions failed
return builder.build();
}
dbMap.put(si.getName(), si);
return Response.accepted().build();
}
290
Mr. Sriman Web Services
20.19 Security
package com.sw.dto;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlType
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "statusInfo")
public class StatusInfo {
private String pancard;
private String status;
package com.sw.resource;
import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.SecurityContext;
import com.sw.dto.StatusInfo;
@Path("/it")
public class ITResource {
@Context
private SecurityContext securityContext;
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("/{pancard}")
public String getITRVStatus(@PathParam("pancard") String pancard) {
if (securityContext.isUserInRole("ADMIN")) {
return "Internal Approval in progress";
} else if (securityContext.isUserInRole("USER")) {
return "In progress";
}
return null;
}
291
Mr. Sriman Web Services
@GET
@Path("/{pancard}")
@Produces(MediaType.APPLICATION_XML)
@RolesAllowed("ADMIN")
public StatusInfo getITRVSubmission(@PathParam("pancard") String pancard) {
StatusInfo si = new StatusInfo();
si.setPancard(pancard);
si.setStatus("Approved");
return si;
}
}
292
Mr. Sriman Web Services
<web-resource-collection>
<web-resource-name>ITResource</web-resource-name>
<url-pattern>/rest/it/*</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>ADMIN</role-name>
<role-name>USER</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
</web-app>
import java.util.HashSet;
import java.util.Set;
import javax.servlet.ServletContext;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@ApplicationPath("/rest")
public class JAXRSSpringIntegApplication extends Application {
private Set<Object> singletons;
resourceConfigPath = context.getInitParameter("resourceConfigPath");
@Override
public Set<Object> getSingletons() {
return singletons;
}
293
Mr. Sriman Web Services
package com.jrs.business;
package com.jrs.resource;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.jrs.business.FlightService;
@Path("/flight")
public class FlightResource {
private FlightService flightService;
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("/{flightno}")
public float getPrice(@PathParam("flightno") String flightNo) {
return flightService.getAirFare(flightNo);
}
294
Mr. Sriman Web Services
295
Mr. Sriman Web Services
XML VS JSON
296
Mr. Sriman Web Services
21 XML VS JSON
Abbreviation:
• XML Stands for Extensible Markup language
• Json stands for Javascrip object notation
Meaning:
• XML is a markup language that defines set of rules for encoding documents in the
format that is both human readable and machine readable
Json is a text-based open standard designed for human-readable data interchange. It is
derived from JavaScript scripting language for representing simple data structures and
associated arrays, called objects. Json format is often used for serializing and
transmitting structured data over the network connection. Primarily to transmit data
between server and a web application serving an alternative to XML.
Type of format:
• XML - Markup languange
• Json - Data interchange
Extended from:
• XML - SGML
• Json - JavaScript.
Developed By:
• XML - World Wide Web Consortium
• The Json format was originally specified by Douglas Crockford for using it at State
Software.
Data types:
• XML – Does not provide any notation of data types. One must rely on XML schema for
adding type information.
• Json – Provides scalar data types and the ability to express structured data through
arrays and objects.
Null support:
• XML - Requires the use of xsi:nil on elements in an XML instance document plus an
import of the appropriate namespace
• Json - Natively recognized the null
Comments:
• XML – Native support and usually available through API
• Json – Not supported
297
Mr. Sriman Web Services
Namespaces:
• XML – Supports namespaces which elements the risk of name collisions when
combining the documents
• Json – No concept of namespaces. Naming collisions are avoided by nesting objects or
using prefix in an object member
Formatting decisions:
• XML – Requires a greater effort to decide how to map application types to XML
elements and attributes
• Json – Simple provides a much more direct mapping of application data
Size:
• XML – Documents tends to be lengthy in size
• Json – Syntax is very terse and yields formatted text where most of the space is
consumed
Parsing in Javascript:
• XML – Requires XML DOM implementation and additional application code to map text
back to Javascript objects
• Json – No additional code is required apart from using aval() function
Learning curve:
• XML – Generally tends to use of several technologies in concert: Xpath, XML Schema,
XSLT, DOM, XML Namespaces etc.
• Json – Already familiar with developers through Javascript
Tools:
• XML – Enjoy a mature set of tools widely available
• Json – Rich tool support - scarce
22 SOAP VS REST
22.1 REST
• It is not a protocol rather architectural style
• Completely stateless
• Provide good caching mechanism over Http protocol (can be used to scale-up
when the data is not frequently modified on the resource)
• It is Web Style (SOAP is distributed technology)
• There is no standard definition language to expose the interface of resource to
the client. They need to have common understanding of content need to be
passed (depends on response content container hypermedia)
• It is suitable for few applications such as Mobile platform or PDA’s (as SOAP is
eliminated)
• These are easy to integrate with existing Web applications, they don’t need any
changes in existing architecture
• It doesn’t enforce the message format, it can be XML or JSON
298
Mr. Sriman Web Services
22.2 SOAP
• SOAP is a XML-based messaging protocol
• It has a specification, but REST has none
• SOAP has specification for stateful implementation
• No Caching support
• It has a standard description language WSDL using which consumer and
provider can exchange the data over standard interface
• SOAP requires less plumbing code as transactions, security, addressing etc has
been provided.
• SOAP is XML based protocol and will not supports any other formats like JSON
299