Вы находитесь на странице: 1из 27

JERSEY Implementation:

|-Set up to work with JERSEY

|-Bootstrapping mechanisms for JAX-RS ServletContainer Which is specific to JERSEY

1. Auto scan

|-Difference between the JERSEY Runtime (ServletContainer) and RESTEasy


Runtime (HttpServletDispatcher)

a) Concrete Resource (classes scanning) scanning

b) Jersey packages Scanning including sub packages

2. Custom Application subclass and Controlling Scopes

3. Custom ResourceConfig subclass and Controlling Scopes

4. Servlet Plugability Mechanism (ServletContainer will be automatically added by


JERSEY)

a) JAX-RS API Application class without an Application subclass

b) JAX-RS API Application with a custom Application subclass or ResourceConfig


subclass

5. without web.xml

a) Using @ApplicationPath with Custom Application

b) Using @ApplicationPath with Custom ResourceConfig

|-Internal Code for without web.xml Using @ApplicationPath with Custom Application
or Custom ResourceConfig

|-Configuring the JAX-RS Runtime which will works agnostic to the Implementation

(Or)

Recommended Bootstrapping or best Runtime bootstrapping mechanism

|-Internal Req flow of RESTful services

Set up to work with JERSEY:

When we are working with Glassfish Server we no need to download the JERSEY binary
distribution bcz Glass fish server by default contains all the jars.

But when we are working with other containers we need to Download JERSEY
Implementation Binary Distribution which jaxrs-ri-2.4.1 (RI means reference
Implementation also called as JERSEY Implementation) which can deployed with any
container that means agnostic to the containers.

Say Extract Here the jaxrs-ri-2.4.1.zip file then it will shows as follows.

jaxrs-ri

|-api (Which contains javax.ws.rs-api-2.0.jar which is JAX-RS 2.0 API)

|-ext (contains JAX-RS 1.2 API annotations jars like javax.annotation-api-1.2)


|-lib (contains jersey-container-servlet.jar and its related)

Copy all the jars that are there from api, ext, lib and paste in the lib directory then
start working the application.

Bootstrapping Mechanisms of JAX-RS Runtime which is specific to the JERSEY


Implementation:

Initially Sun Ms. has provided Runtime as

com.sun.xml.ws.rs.servlet.ServletContainer and then goes on Implementation will


shifted as Glassfish server to work with 2.0 that is the reason they renamed Runtime
name as org.glassfish.jersey.servlet.ServletContainer

In order to configure the JAX-RS Runtime the Sun Ms. has provided JERSEY Runtime
which is called as org.glassfish.jersey.servlet.ServletContainer which will acts as
Runtime for the RESTful services.

class ServletContainer extends HttpServlet implements Filter, Container {

public void init() {

protected void service(HttpServletRequest req, HttpServletResponse res) {

1. Auto scan:

<servlet>

<servlet-name>jersey</servlet-name>

<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>jersey</servlet-name>

<url-pattern>/*</url-pattern>

</servlet-mapping>

The URL that we have configured "/*" is an suspecious URL bcz if we have one more
servlet hence we need to configure "prefix" in case of RESTEasy but in case of JERSEY
we can automatically configure URL as "/rest/*" without any prefix so it mapps and
prefixes "/rest" for each and every Resource class
<servlet>

<servlet-name>jersey</servlet-name>

<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>jersey</servlet-name>

<url-pattern>/rest/*</url-pattern>

</servlet-mapping>

Difference between the JERSEY Runtime (ServletContainer) and RESTEasy


Runtime (HttpServletDispatcher):

http://host:port/ContextRoot/extra path URL (anything)

In case of RESTEasy if we configure prefix as "rest" then also it starts matching URL
from "ContextRoot" then "rest" then extra path URL (like ContextRoot/rest/courier).

But in case of JERSEY it starts matching URL direclty form the /rest but not from the
"ContextRoot" hence it quickly forwards the req to the Resource class (like
/rest/courier).

That means JERSEY Runtime (ServletContainer) will uses only extra path URI only to
map the req but

RESTEasy uses complete URL to map the req.

If we try to access using

http://localhost:8080/1DTDCIntraCourierWeb/rest/courier?source=hyd&dest=blr&w
eight=65

then it will not works bcz auto-scan of Resources classes cannot done automatically
hence we need to configure the auto scan of the Resources.

Auto-scan of Resources can be done in 2-ways as part of init-params in case of JERSEY

a) Concrete Resource (classes scanning) scanning

b) Jersey packages Scanning including sub packages

a) Concrete Resource (classes scanning) scanning:

<init-param>

<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>com.dtdc.jersey.resource.DTDCCourierResource</param-value>

</init-param>

We can pass multiple class names as comma (,) separated.

Access the Application Resource as

http://localhost:8080/1.1BootStrapUsingClassNames/rest/courier?source=hyd&dest
=blr&weight=65

b) Jersey packages Scanning including sub packages:

<init-param>

<param-name>jersey.config.server.provider.packages</param-name>

<param-value>com.dtdc.jersey.resource</param-value>

</init-param>

We can pass multiple packages as comma (,) separated.

It will Scans only the Resources that are there in that package only but not the sub
packages that are there in that package. SO in order to read the Resource classes that
are there in sub-packages also we need to configure using
"jersey.config.server.provider.scanning.recursive" as true

<init-param>

<param-name>jersey.config.server.provider.packages</param-name>

<param-value>com.dtdc.jersey.resource</param-value>

</init-param>

<init-param>

<param-name>jersey.config.server.provider.scanning.recursive</param-name>

<param-value>true</param-value>

</init-param>

The subpackages "jersey.config.server.provider.scanning.recursive" in not mandatory


it optional.
Access the applicarion with multiple req's

http://localhost:8080/1.2BootStrapUsingPackageNames/rest/courier?source=hyd&d
est=blr&weight=65

HashCode: 867934004 Price is : 233.3

HashCode: 2098867844 Price is : 233.3

That means by default RESTEasy and JERSEY Runtimes makes our Resource classes
as non-singleton (prototype) hence thread safe.

If we want we can make Resource as Singleton using Application class.

2. Custom Application subclass and Controlling Scopes:

class DtdcCourierApplicationConfig extends Application {

private Set<Class<?>> classes;

private Set<Object> singletons;

@Override

public Set<Object> getSingletons() {

return singletons;

@Override

public Set<Class<?>> getClasses() {

return classes;

web.xml:

<servlet>

<servlet-name>jersey</servlet-name>

<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

<init-param>

<param-name>javax.ws.rs.Application</param-name>

<param-value>com.dtdc.jersey.common.DtdcCourierApplicationConfig</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>

If we have multiple resources as part of the application which we wanted to make


singletons and prototypes which is difficult to manage as part of the
DtdcCourierApplicationConfig class bcz if we added one more Resource class then we
need to change the code that is there in the DtdcCourierApplicationConfig class which
is difficult to manage that's where JERSEY has provided one Implementation class for
the Application class which is called as ResourceConfig (Concrete class that is given
by JERSEY Implementation)

3. Custom ResourceConfig subclass and Controlling Scopes:

So now we no need to override the methods rather we need to tell which classes we
wanted to make singletons and which classes wants to be non-singleton, that means
we can use ResourceConfig class to configure ServletContainer easily and we can
control the scopes in easier manner as compared to the Application class.

class DtdcCourierResourceConfig extends ResourceConfig {

// JERSEY ServletContainer will calls this ResourceConfig class

public DtdcCourierResourceConfig() {

// packages(-,-) makes to load the Resources that are there

// in that packages and its sub packages (true indicates sub-packages)

packages(true, "com.dtdc.jersey.resource");

// register() used for to make a class as singleton

register(new DTDCCourierResource());

web.xml:

<servlet>
<servlet-name>jersey</servlet-name>

<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

<init-param>

<param-name>javax.ws.rs.Application</param-name>

<param-value>com.dtdc.jersey.common.DtdcCourierResourceConfig</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>

Internal code:

class ResourceConfig extends Application {

private transient Set<Class<?>> cachedClasses;

private transient Set<Class<?>> cachedClassesView;

private transient Set<Object> cachedSingletons;

private transient Set<Object> cachedSingletonsView;

private volatile State state;

//It will gegisters the classes which are singleton and which are prototypes

Access the Application with multiple req's

http://localhost:8080/3BootStrapUsingControlScopesUsingResourceConfig/

rest/courier?source=hyd&dest=blr&weight=65

HashCode: 514701596 Price is : 233.3

HashCode: 514701596 Price is : 233.3

What is the purpose of ResourceConfig class that is there in the JERSEY


Implementation?
JERSEY Implementation has provided Implementation for the Application class to
register/configure the Runtime and manage the scopes of our Resource classes
without overriding the methods so that we easy the configuration of the RESTful
applications.

4. Servlet Pluggability Mechanism (ServletContainer will automatically added


by JERSEY):

The purpose this mechanism is without knowing the Implementation Runtime class
we can configure the Runtime

a) JAX-RS API Application class without an Application subclass:

<!-- Servlet declaration can be omitted in which case

it would be automatically added by Jersey -->

<servlet>

<servlet-name>javax.ws.rs.core.Application</servlet-name>

</servlet>

<servlet-mapping>

<servlet-name>javax.ws.rs.core.Application</servlet-name>

<url-pattern>/rest/*</url-pattern>

</servlet-mapping>

http://localhost:8080/4.1BootStrapUsingServletPluggabilityMechanism/

rest/courier?source=hyd&dest=blr&weight=65

HashCode: 509691099 Price is : 233.3

HashCode: 1112200388 Price is : 233.3

b) JAX-RS API Application with a custom Application or ResourceConfig


subclass:

Here if we write our application class extending from Application class then we need
to override the methods but if we write our ResourceConfig class extending from
ResourceConfig then easily bootstrap the Runtime and we can control the scope of our
classes easily.
Here we are creating our class using Resource but we are configuring in web.xml as
Application class only rather than bcz ResourceConfig is sub class of Application hence
it can detected by JAX-RS JERSEY easily. But if we configure ResourceConfig it will not
detects.

(i) Using Custom Application class:

class DtdcCourierApplication extends Application {

private Set<Object> singletons;

public DtdcCourierApplication() {

singletons = new HashSet<Object>();

singletons.add(new DTDCCourierResource());

@Override

public Set<Object> getSingletons() {

return singletons;

<!-- Servlet declaration can be omitted in which case it would be

automatically added by Jersey -->

<servlet>

<servlet-name>com.dtdc.jersey.common.DtdcCourierApplication</servlet-name>

</servlet>

<servlet-mapping>

<servlet-name>com.dtdc.jersey.common.DtdcCourierApplication</servlet-name>

<url-pattern>/rest/*</url-pattern>

</servlet-mapping>

Access the application with multiple req's


http://localhost:8080/4.2.1BootStrapUsingServletPluggabilityUsingCustomApplicatio
n/rest/courier?source=hyd&dest=blr&weight=65

HashCode: 1711571922 Price is : 233.3

HashCode: 1711571922 Price is : 233.3

(ii) Using Custom ResourceConfig class:

class DtdcCourierResourceConfig extends ResourceConfig {

// JERSEY ServletContainer will calls this Resource class

public DtdcCourierResourceConfig() {

// packages(-,-) makes to load the Resources that are there

// in that packages and its sub packages (true indicates sub-packages)

packages(true, "com.dtdc.jersey.resource");

// register() used for to make a class as singleton

register(new DTDCCourierResource());

<!-- Servlet declaration can be omitted in which case it would be

automatically added by Jersey -->

<servlet>

<servlet-name>com.dtdc.jersey.common.DtdcCourierResourceConfig</servlet-
name>

</servlet>

<servlet-mapping>

<servlet-name>com.dtdc.jersey.common.DtdcCourierResourceConfig</servlet-
name>

<url-pattern>/rest/*</url-pattern>

</servlet-mapping>

Access the application with multiple req's as


http://localhost:8080/4.2.2BootStrapUsingServletPluggabilityUsingCustomResource
Config/rest/courier?source=hyd&dest=blr&weight=65

HashCode: 1009206429 Price is : 233.3

HashCode: 1009206429 Price is : 233.3

5. without web.xml:

a) Using @ApplicationPath with Custom Application:

@ApplicationPath("/rest/*")

class DtdcCourierApplication extends Application {

private Set<Object> singletons;

public DtdcCourierApplication() {

singletons = new HashSet<Object>();

singletons.add(new DTDCCourierResource());

@Override

public Set<Object> getSingletons() {

return singletons;

Access the application with multiple req's

http://localhost:8080/5.1BootStrapWithoutWebXmlUsingCustomApplication/

rest/courier?source=hyd&dest=blr&weight=65

HashCode: 458565605 Price is : 233.3

HashCode: 458565605 Price is : 233.3

b) Using @ApplicationPath with Custom ResourceConfig:

@ApplicationPath("/rest/*")

class DtdcCourierResourceConfig extends ResourceConfig {


public DtdcCourierResourceConfig() {

// used to make as prototype

packages("com.dtdc.jersey.resource");

// used to make as singleton

register(new DTDCCourierResource());

Access the application with multiple req's

http://localhost:8080/5.2BootStrapWithoutWebXmlUsingCustomResourceConfig/

rest/courier?source=hyd&dest=blr&weight=65

HashCode: 238565605 Price is : 233.3

HashCode: 238565605 Price is : 233.3

Internal Code for without web.xml Using @ApplicationPath with Custom


Application or Custom ResourceConfig:

class JerseyServletContainerInitializer implements

ServletContainerInitializer {

public void onStartup(Set<Class<?>> classes,

ServletContext servletContext) {

if (Custom Application class is available) {

// It looks for the Application class so control goes to our Custom Application

class and identifies the @ApplicationPath("/rest/*") to configure the URL

ServletContainer(JERSEY Runtime)

// Then gets all this data from the Custom Application class and @ApplicationPath
and creates the ResourceConfig obj and places with in the resourceConfig and

then gets the servletContext obj and places with in the resourceConfig now all

the meta data is available with ResourceConfig now

JerseyServletContainerInitializer will creates or hook-up the ServletContainer

by passing resourceConfig obj as follows.

// Creates the obj of ResourceConfig

ResourceConfig resourceConfig=

ResourceConfig.add(getContextParams(servletContext));

} else {

// It looks for the Application class but it is absract hence it looks for the

Custom Application class but it is not there hence it will looks for the default

Implementation called as ResouceConfig so now it will creates the

resourceConfig class obj.

// During creation of the ResourceConfig class obj our Custom ResourceConfig

class constructor will be called (bcz we extends from the ResourceConfig) and

in our Custom ResourceConfig class constructor we called the super class

method packages(true,"packageName") hence control goes to the super

ResourceConfig constructor and it will calls the packages(-,-) with method param

inputs that we passed and then it gets the URL from the

@ApplicationPath("/rest/*") to configure ServletContainer then ResourceConfig

obj will be created with all the requied data and it passes servletContext obj to

the ResourceConfig obj so that now all the meta data is available with

ResourceConfig now JerseyServletContainerInitializer will creates or hook-up the

ServletContainer by passing resourceConfig obj as follows.

// Creates the obj of ResourceConfig

ResourceConfig
resourceConfig=ResourceConfig.add(getContextParams(servletContext));

// Creates the JERSEY Runtime (ServletContainer)


ServletContainer jerseyContainer=new ServletContainer(resourceConfig);

// configures load on startup for ServletContainer as "1"

}
Configuring the JAX-RS Runtime which will works agnostic to the
Implementation:

(Or)

Recommended Bootstrapping or best Runtime bootstrapping mechanism:

Application is an JAX-RS API provided class and ResourceConfig class is JERSEY


provided class (org.glassfish.jersey.server.ResourceConfig).

JAX-RS provides a deployment agnostic to the containers or JAX-RS Implementation


vendors as well if we bootstrap the Runtime using abstract class Application for
declaring root resource and provider classes, and root resource and provider singleton
instances. That means if we write the bootstrapping using Application class we can
switch from one Implementation vendor to another Implementation vendor without
changing Runtime as well bcz Application class itself picks up the Runtime of
corresponding vendor bcz we annotated with JAX-RS API Annotation so it will takes
care.

Hence recommended Bootstrapping mechanism is

The Best Bootstrapping is 5-a) without web.xml Using @ApplicationPath with Custom
Application class which can works with Agnostic to the Implementation vendor and its
diagram is shown in below figure.

The Diagrammatical representation is shown below depicts the agnostic JAX-RS


Runtime creation as follows.
Internal Req flow of RESTful services:

Runtime will takes the req identifies the incoming URL with Resource class URL which
is annotated with @Path and forwards the req to that Resource class.

For every req it will not goes to the application classes rather it will reads all the
Resource classes at one single shot and places as Resource Meta data. Every Runtime
will maintains not only Resource Meta data in addition to this it maintains

Provider Meta data,

Resource Meta data,

Converter meta data,

Readers meta data,

Writers meta data.

Once req comes to the Runtime then it goes to the meta data and identifies the
corresponding Resource class using URL and calls the corresponding method based on
the incoming req method type and calls the method with input data and then business
method performs the logic and returns the res based on the @Produces("text/palin")
now Runtime will dispatches the resp by using res.getWriter();

As Runtime holds resource Meta-data it highly recommended to configure load on


start-up as “1” for the JAX-RS Runtime.
Use case related all the Http methods:

Use case: Oxygen Wallet REST-Resource:

Instead of paying the money through the credit card by every time providing the credit
card details to the every e-commerce site we can use Oxygen Wallet which hides the
credit card details to the other web sites bcz initially we add the money to the Oxygen
Wallet so that we can order any items from any web sites bcz Oxygen ECash Wallet
will provides the business through the web services or RESTful services to the e-
commerce web sites so that credit card details will be hidden from the e-commerce
web sites bcz transaction will done from the Oxygen Wallet to the e-commerce sites
so that confidential data will be hidden from the each and every web site and
advantage is with one Oxygen Wallet we contribute to any web site.

Jbong, Snapdeal, flipkart, paytm etc will talks to the OxygenWallet that has provided
by the Oxygen via web services or RESTful services (without giving the DB details of
the end-users) so that end-user can order the items without giving the confidential to
eacha and every site bcz end-user will maintains the cash in the OxygenWallet so that
end-user will pays via OxygenWallet irrespective of the e-commerce.

@Path("/oxygen-ecash")

public class OxygenECashAgent {

private AtomicInteger autoWalletID;

private Map<Integer, Wallet> walletMap;

public OxygenECashAgent() {

autoWalletID = new AtomicInteger(1);

walletMap = new ConcurrentHashMap<Integer, Wallet>();

// Here we are taking ConcurrentHashMap to avoid the race condtions

or non-thread safe issues

}
@GET

@Produces(MediaType.TEXT_PLAIN)

public float getWalletBalance(@QueryParam("walletID") int walletID) {

@POST

public Wallet createWallet(User user) {

return wallet;

@PUT

public Wallet addCash(Transact transact) {

@DELETE

public Wallet deactivate(String walletId) {

Note:

GET-gets the data form Wallet

POST-creates new Wallet

PUT-updates/adds the money to the existing Wallet

DELETE-deactivates the wallet

We cannot send the obj of data through the query Params hence will pass the data in
the req body but if we send the data in the form Serializable bits then it not becomes
interoperable hence we will send the data in the xml format which makes interoperable
and here we can send any data format but in case of Web services we cannot send
any format apart from the xml.
Hence we cannot send directly xml hence we need to use DOM/SAX parsing to convert
into obj.

@Path("/oxygen-ecash")

public class OxygenECashAgent {

private AtomicInteger autoWalletID;

private Map<Integer, Wallet> walletMap;

public OxygenECashAgent() {

autoWalletID = new AtomicInteger(1);

walletMap = new ConcurrentHashMap<Integer, Wallet>();

// Resource method for GET req

@GET

@Produces(MediaType.TEXT_PLAIN)

public float getWalletBalance(@QueryParam("walletID") int walletID) {

return 0.0f;

@POST

@Consumes(MediaType.APPLICATION_XML)

@Produces(MediaType.APPLICATION_XML)

public StreamingOutput createWallet(InputStream in) {

// build the User obj

user = buildUser(in);

/*

Create DataStreamingOuput obj and convert business obj(Wallet) into

DataStreamingOuput type and return so that JAX-RS Runtime will takes

this DataStreamingOuput obj data and returns to the client in

specified format by calling write(OutputStream) at run time


*/

walletStreamingOutput = new DataStreamingOuput(convertWallet(wallet));

/*

* We can return sub class ref for super class type that means

* DataStreamingOutput is sub class of StreamingOutput class so here we

* are returning obj of sub class so it takes this returned obj and on

* this obj it will class will calls write(OutputStream) so that

* response will be sent.

*/

return walletStreamingOutput;

// Resource Method for PUT req

@PUT

@Consumes(MediaType.APPLICATION_XML)

@Produces(MediaType.APPLICATION_XML)

public StreamingOutput addCash(InputStream in) {

// Build AddMoney obj

addMoney = buildAddMoney(in);

/*

Create DataStreamingOuput obj and convert business obj(Wallet) into

DataStreamingOuput type and return so that JAX-RS Runtime will takes

this DataStreamingOuput obj data and returns to the client in

specified format by calling write(OutputStream) at run time

*/

return new DataStreamingOuput(convertWallet(wallet));

// Resource Method for DELETE req

@DELETE
@Produces(MediaType.APPLICATION_XML)

public StreamingOutput deactivateWallet(@QueryParam("walletID") int walletID) {

/*

Create DataStreamingOuput obj and convert business obj(settlement) into

DataStreamingOuput type and return so that JAX-RS Runtime will takes

this DataStreamingOuput obj data and returns to the client in

specified format by calling write(OutputStream) at run time

*/

return new DataStreamingOuput(convertFinalSettlement(settlement));

/*

Helper or Parsing methods which are used to build business obj for

Resource methods

*/

// Building User obj

private User buildUser(InputStream in) {

return user;

// Building AddMoney obj

private AddMoney buildAddMoney(InputStream in) {

return addMoney;

/*

Appending/Converting the business obj to StringBuffer in the

form of xml format

*/
// converting User obj to xml

private String convertWallet(Wallet wallet) {

// Convert StringBuffer obj into String obj

return buffer.toString();

// converting FinalSettlement obj to xml

private String convertFinalSettlement(FinalSettlement settlement) {

// Convert StringBuffer obj into String obj

return buffer.toString();

/*

Making the contract with JAX-RS Runtime so that output will be displayed

to the client through the JAX-RS Runtime via JEE-Container (Actually

JAX-RS in-turn gives data to the JEE-Container which will displays the

data to the client which is called as CallBack)

*/

private final class DataStreamingOuput implements StreamingOutput {

private String data;

public DataStreamingOuput(String data) {

this.data = data;

// This method will be called by the JAX-RS Runtime after receiving the

// DataStreamingOuput obj that has been returned by the Resource method

@Override

public void write(OutputStream out) {

PrintWriter writer = new PrintWriter(out);

writer.print(data);
writer.close();

// If we close the "out" obj then only res will be committed

out.close();

Did u write @Consumes(application/xml) for the GET request?

No, Bcz @Consume is used to recive the data by the Resource class in which format
the end-user has over the req. In case of GET will cannot send the data over the body
bcz for GET req req body will not be there hence we can send the data through the
Query param or req headers but we cannot send the xml format data over the body
for the GET hence we will not write the @Consume("application/xml") or
@Consume("text/palin") for GET req bcz we not sending the over the body hence our
Resource class cannot consumes the data in the form of xml or text rather it will
accepts in the form of Query params or using headers hence we should not write
@Consume on top of the GET req.

Note:

For DELETE we send the data over req body as well but here in this use case not
required that is the reason we didn't written @Consume, if we want we send xml data
over the req body then we can write for that also @Consume.

Here in @Produces(MediaType.TEXT_PLAIN) MediaType is an Enum which contains


normal Constant as TEXT_PLAIN.

InputStream:

The JAX-RS Runtime wraps the req data and populates into the InputStream as String
data if it is not a primitive data types.

If it primitive data types then it automatically converts into that corresponding types.

StreamingOutput:

The JAX-RS runtime will takes the resonse in the form of StreamingOutput hence we
need to return in the form of StreamingOutput obj. So now JAX-RS will takes the
StreamingOutput obj whichis in the form String now it displays in the proper way as
xml format bcz we specified as @Produces(“application/xml”) or
@Produces(MediaType.APPLICATION_XML). If we didn’t specify the @Produces then
it will displays as String xml but in the formatted xml.

AutomicInteger:

AutomicInteger is an automatic increment integer which will be Thread safe even


though multiple threads are acting and it has been added in JDK-1.5

Send the req and check the response:

1 POST req:
Open the ARC Cleint

Step: 1

Type in URL bar as

http://localhost:8080/7OxygenWeb/resources/oxygen-ecash

Step: 2

Select POST then click on the Form and in the Form give as follows

Content-Type as = application/xml

Step: 3

Then below this one more option is there to send the data as xml so click on Raw then
write the xml as follows without any spaces

<?xml version="1.0" encoding="utf-8" ?><user><username>DB

Reddy</username><mobile>2232665</mobile><email>S/O Ranga Reddy


</email></user>

Send the req and observe the output.

Response:

<wallet><walletID>2</walletID><user><username>db</username><mobile>223
2665</mobile><email>dbr@</email></user><balance>0.0</balance><status>A
ctive</status></wallet>

Note:

JAX-RS will takes the StreamingOutput obj which is in the form String now it displays
in the proper way as xml format bcz we specified as @Produces(“application/xml”) or
@Produces(MediaType.APPLICATION_XML). If we didn’t specify the @Produces then
it will displays as String xml but in the formatted xml.

2 PUT:

Send the req with same Wallet Id that we have created so that we can add the amount
to that wallet.

<?xml version="1.0" encoding="utf-8" ?>


<addMoney><walletID>2</walletID><fromAccount>DB Reddy

</fromAccount><amount>9000</amount></addMoney>

Response:

<wallet><walletID>2</walletID><user><username>DB Reddy

</username><mobile>2232</mobile><email>dbr@</email></user><balance>90
00.0</balance><status>Active</status></wallet>
3 GET:

Send the req with GET req and walletID as same as we added the money

http://localhost:8080/7OxygenWeb/resources/oxygen-ecash?walletID=2

Response:

9000.0

4 DELETE:

Send the req with same wallet that we had created

http://localhost:8080/7OxygenWeb/resources/oxygen-ecash?walletID=2

Response:

<settlement><walletID>2</walletID><username>DB
Reddy</username><balance>9000.0</balance><status>Your Wallet has been
successfully De-Acivated</status></settlement>

5 GET:

Try to send again the req to check whether the account has been de-activated or not

http://localhost:8080/7OxygenWeb/resources/oxygen-ecash?walletID=2

Reponse:

0.0 (Hence account has been de-activated successfully)

Вам также может понравиться