Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

CXF

...

has

...

an

...

initial

...

implementation

...

of

...

JAX-RS

...

(JSR-311):

...

Java

...

API

...

for

...

RESTfulWeb

...

Services.

...

JAX-RS

...

provides

...

a

...

more

...

standard

...

way

...

to

...

build

...

RESTful

...

services

...

in

...

Java.

...

JAX-RS

...

related

...

demos

...

are

...

located

...

under

...

samples\jax_rs

...

directory

...

(CXF

...

2.1

...

only).

...

Understanding

...

the

...

basics

...

You

...

are

...

encouraged

...

to

...

read

...

JAX-RS

...

spec

...

to

...

find

...

out

...

information

...

not

...

covered

...

by

...

this

...

documentation.

...

Resource

...

class

...

A

...

resource

...

class

...

is

...

a

...

Java

...

Class

...

annotated

...

with

...

JAX-RS

...

annotations

...

to

...

represent

...

a

...

Web

...

resource.

...

A

...

typical

...

resource

...

class

...

in

...

JAX-RS

...

looks

...

like

...

below:

Code Block
java
java

{code:java}
package demo.jaxrs.server;

import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.GET;
import javax.ws.rs.ProduceMime;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

@Path("/customerservice/")
@ProduceMime("application/xml")
public class CustomerService {

    public CustomerService() {
    }

    @GET
    public Customers getCustomers() {
        ......
    }

    @GET
    @Path("/customers/{id}")
    @ProduceMime("application/json")
    public Customer getCustomer(@PathParam("id") String id) {
        ......
    }

    @PUT
    @Path("/customers/{id}")
    @ConsumeMime("application/xml")
    public Response updateCustomer(@PathParam("id") Long id, Customer customer) {
        ......
    }

    @POST
    @Path("/customers")
    public Response addCustomer(Customer customer) {
        ......
    }

    @DELETE
    @Path("/customers/{id}/")
    public Response deleteCustomer(@PathParam("id") String id) {
        ......
    }

    @Path("/orders/{orderId}/")
    public Order getOrder(@PathParam("orderId") String orderId) {
       ......
    }
}
{code}

Customer

...

resource

...

class

...

can

...

handle

...

requests

...

starting

...

from

...

/customerservice.

...

When

...

/customerservice

...

request

...

is

...

matched

...

to

...

this

...

class,

...

its

...

getCustomers()

...

method

...

will

...

be

...

selected.

...

updateCustomer(),

...

deleteCustomer()

...

and

...

addCustomer()

...

are

...

used

...

to

...

serve

...

POST,

...

PUT

...

and

...

DELETE

...

requests

...

starting

...

from

...

/customerservice/customer,

...

while

...

getOrder()

...

method

...

delegates

...

the

...

handling

...

of

...

requests

...

like

...

/customerservice/orders/1

...

to

...

a

...

subresource

...

locator

...

Order.

...

ProduceMime

...

annotation

...

is

...

used

...

to

...

specify

...

the

...

format

...

of

...

the

...

response.

...

When

...

not

...

available

...

on

...

the

...

method,

...

it's

...

inherited

...

from

...

a

...

class,

...

and

...

if

...

it's

...

not

...

available

...

on

...

the

...

class

...

then

...

it's

...

inherited

...

from

...

a

...

corresponding

...

message

...

body

...

writer,

...

if

...

any.

...

Default

...

value

...

is

...

/

...

,

...

but

...

it's

...

recommended

...

that

...

some

...

definite

...

value

...

is

...

specified.

...

The

...

same

...

applies

...

to

...

ConsumeMime,

...

only

...

it's

...

message

...

body

...

readers

...

are

...

checked

...

as

...

the

...

last

...

resort.

...

For

...

example,

...

getCustomers()

...

method

...

inherits

...

the

...

ProduceMime

...

annotation

...

from

...

its

...

class,

...

while

...

getCustomer()

...

method

...

overrides

...

it

...

with

...

its

...

own

...

value.

...

@Path

@Path annotation is applied to resource classes or methods. The value of @Path annotation is a relative URI path follows the URI Template format.

More information about Path annotations can be found from JAX-RS spec section 2.3.

HTTP Method

JAX-RS specification defines a number of annotations such as @GET, @PUT, @POST and @DELETE. Using an @HttpMethod designator, one can create a custom annotation such as @Update or @Patch

Return types

Either javax.ws.rs.core.Response

...

or

...

custom

...

type

...

can

...

be

...

returned.

...

javax.ws.rs.core.Response

...

can

...

be

...

used

...

to

...

set

...

the

...

HTTP

...

response

...

code,

...

headers

...

and

...

entity.

Exception handling

One can either throw an unchecked WebApplicationException or return Response with a proper error code set.
The former option may be a better option when no JAX-RS types can be added to method signatures.

For example :

Code Block
java
java
 

h3. Exception handling

One can either throw an unchecked WebApplicationException or return Response with a proper error code set.
The former option may be a better option when no JAX-RS types can be added to method signatures.

For example :

{code:java}
@Path("/customerservice/")
public class CustomerService {

    
    @PUT
    @Path("/customers/{id}")
    public Response updateCustomer(@PathParam("id") Long id, Customer customer) {
        return Response.status(errorCode).build();
    }

    @POST
    @Path("/customers")
    public Customer addCustomer(Customer customer) {
        throw new WebApplicationException(errorCode);
    }

}

Dealing with Parameters

PathParam annotation is used to map a given Path template variable to a method parameter.
For example :

Code Block
java
java
{code}

h2. Dealing with Parameters

PathParam annotation is used to map a given Path template variable to a method parameter.
For example :

{code:java}

@Path("/customer/{id}")
public class CustomerService {

    
    @PUT
    @Path("{name}")
    public Response updateCustomer(@PathParam("id") Long id, @PathParam("name") String name) {
        ...
    }
}
{code}

In

...

this

...

case

...

a

...

template

...

variable

...

id

...

available

...

from

...

a

...

root

...

class

...

annotation

...

is

...

mapped

...

to

...

a

...

parameter

...

of

...

type

...

Long,

...

while

...

a

...

name

...

variable

...

is

...

mapped

...

to

...

a

...

parameter

...

of

...

type

...

String.

...


Paramaters

...

can

...

be

...

of

...

type

...

String

...

or

...

of

...

any

...

type

...

that

...

have

...

constructors

...

accepting

...

a

...

String

...

argument

...

or

...

static

...

valueOf(String

...

s)

...

methods.

...

JAX-RS

...

PathSegment

...

is

...

also

...

supported.

...

QueryParam,

...

HttpHeader

...

and

...

CookieParam

...

annotations

...

are

...

also

...

supported.

...

Context

...

annotations

...

If

...

a

...

parameter

...

or

...

field

...

of

...

either

...

UriInfo

...

or

...

HttpHeaders

...

or

...

SecurityContext

...

or

...

one

...

of

...

the

...

Servlet

...

types

...

like

...

ServeltContext

...

or

...

MessageBodyWorkers

...

is

...

annotated

...

with

...

a

...

Context

...

annotation

...

then

...

CXF

...

will

...

provide

...

properly

...

initialized

...

instances

...

to

...

the

...

application

...

code.

...

Note

...

that

...

if

...

fields

...

are

...

annotated

...

with

...

Context

...

then

...

care

...

should

...

be

...

taken

...

for

...

singleton

...

resource

...

classes

...

as

...

CXF

...

does

...

not

...

support

...

yet

...

a

...

thread-local

...

injection

...

of

...

Context

...

fields.

...

Injection

...

of

...

contexts

...

into

...

message

...

body

...

providers

...

is

...

not

...

supported

...

yet.

...

Example

...

:

Code Block
java
java


{code:java}
@Path("/customer")
public class CustomerService {
    
    @Context ServletContext sc;
    @Context SecurityContext sc;
    
    @PUT
    public Response updateCustomer(@Context UriInfo u, @Context HttpHeader h, Customer c) {
        ...
    }
}

{code}

h2. Annotation inheritance

Most of the 

Annotation inheritance

Most of the JAX-RS

...

annotations

...

can

...

be

...

inherited

...

from

...

either

...

an

...

interface

...

or

...

a

...

superclass.

...

JAX-RS

...

specification

...

requires

...

that

...

only

...

the

...

ones

...

applied

...

to

...

methods

...

can

...

be

...

inherited.

...

For

...

example

...

:

Code Block
java
java


{code:java}

public interface CustomerService {

    @PUT
    @Path("/customers/{id}")
    Response updateCustomer(Long id, Customer customer) {
        return Response.status(errorCode).build();
    }

    @POST
    @Path("/customers")
    Customer addCustomer(Customer customer) {
        throw new WebApplicationException(errorCode);
    }

}
{code}


@Path("/customerservice/")
public class Customers implements CustomerService {

    
    public Response updateCustomer(@PathParam("id"), Customer customer) {
        return Response.status(errorCode).build();
    }

    public Customer addCustomer(Customer customer) {
        throw new WebApplicationException(errorCode);
    }

}
{code}

Note that annotations applied to the interface are inherited. CXF is not capable yet of inheriting the annotations applied to parameters such as PathParam so at the moment they need to be specified anyway at the root class level. 

Similarly annotations can be inherited from super-classes. 

CXF can inherit annotations applied directly to super-classes such as  

Note that annotations applied to the interface are inherited. CXF is not capable yet of inheriting the annotations applied to parameters such as PathParam so at the moment they need to be specified anyway at the root class level.

Similarly annotations can be inherited from super-classes.

CXF can inherit annotations applied directly to super-classes such as @Path("/customerservice/")

...

which

...

is

...

applied

...

to

...

the

...

Customers

...

class

...

above.

...

It

...

may

...

support

...

the

...

same

...

type

...

of

...

inheritance

...

for

...

interfaces

...

too.

...

Note

...

this

...

is

...

not

...

JAX-RS

...

compliant.

...

Sub-resource

...

locators.

...

A

...

method

...

of

...

a

...

resource

...

class

...

that

...

is

...

annotated

...

with

...

@Path

...

becomes

...

a

...

sub-resource

...

locator

...

when

...

an

...

annotation

...

with

...

an

...

HttpMethod

...

designator

...

like

...

@GET

...

is

...

not

...

present.

...

Sub-resource

...

locators

...

are

...

used

...

to

...

further

...

resolve

...

the

...

object

...

that

...

will

...

handle

...

the

...

request.

...

They

...

can

...

delegate

...

to

...

other

...

sub-resource

...

locators.

...

In

...

the

...

example

...

below,

...

getOrder

...

method

...

is

...

a

...

sub-resource

...

locator:

Code Block
java
java

{code:java}
@Path("/customerservice/")
public class CustomerService {

    @Path("/orders/{orderId}/")
    public Order getOrder(@PathParam("orderId") String orderId) {
       ......
    }
}

@XmlRootElement(name = "Order")
public class Order {
    private long id;

    public Order() {
    }

    public long getId() {
        return id;
    }


    @GET
    @Path("products/{productId}/")
    public Product getProduct(@PathParam("productId")int productId) {
       ......
    }
}
{code}

A

...

HTTP

...

GET

...

request

...

to

...

http://localhost:9000/customerservice/orders/223/products/323

...

is

...

dispatched

...

to

...

getOrder

...

method

...

first.

...

If

...

the

...

Order

...

resource

...

whose

...

id

...

is

...

223

...

is

...

found,

...

the

...

Order

...

223

...

will

...

be

...

used

...

to

...

further

...

resolve

...

Product

...

resource.

...

Eventually,

...

a

...

Product

...

323

...

that

...

belongs

...

to

...

Order

...

223

...

is

...

returned.

...

Message

...

Body

...

Providers

...

JAX-RS

...

relies

...

on

...

MessageBodyReader

...

and

...

MessageBodyWriter

...

implementations

...

to

...

serialize

...

and

...

de-serialize

...

Java

...

types.

...

JAX-RS

...

requires

...

that

...

certain

...

types

...

has

...

to

...

be

...

supported

...

out

...

of

...

the

...

box.

...


By

...

default,

...

CXF

...

supports

...

String,

...

byte[],

...

InputStream,

...

File,

...

JAXP

...

Source,

...

JAXB-annotated

...

types

...

with

...

application/xml

...

and

...

application/json

...

formats

...

(see

...

below).

...

JAX-RS

...

MultivaluedMap

...

is

...

also

...

supported

...

for

...


form

...

contents.

...

Support

...

for

...

other

...

types

...

like

...

Reader

...

and

...

StreamingOutput

...

is

...

on

...

the

...

way.

...

Custom Message Body Providers

It's

...

likely

...

that

...

a

...

given

...

application

...

may

...

need

...

to

...

deal

...

with

...

types

...

which

...

are

...

not

...

supported

...

by

...

default.

...


Alternatively,

...

developers

...

may

...

want

...

to

...

provide

...

a

...

more

...

efficient

...

support

...

for

...

handling

...

default

...

types

...

such

...

as

...

InputStream.

...

Here's

...

an

...

example

...

of

...

a

...

custom

...

MessageBodyReader

...

for

...

InputStream

...

(0.7

...

jax-rs

...

api)

...

:

Code Block
java
java


{code:java}

@ConsumeMime("application/octet-stream")
@Provider
public class InputStreamProvider implements MessageBodyReader<InputStream> {

    
    public boolean isReadable(Class<InputStream> type, Type genericType, Annotation[] annotations) {
        return InputStream.class.isAssignableFrom(type);
    }

    public InputStream readFrom(Class<InputStream> clazz, Type t, MediaType mt, 
                         Annotation[] a, MultivaluedMap<String, String> headers, InputStream is) 
        throws IOException {
        return new FilterInputStream(is) {
             @Override
             public int read(byte[] b) throws IOException {
                 // filter out some bytes
             }              
        }     
    }
}

{code}

and

...

here's

...

an

...

example

...

of

...

a

...

custom

...

MessageBodyWriter

...

for

...

Long

...

(0.7

...

jax-rs

...

api)

...

:

Code Block
java
java


{code:java}

@ProduceMime("text/plain")
@Provider
public class LongProvider implements MessageBodyWriter<Long> {

    public long getSize(Long l) {
        return -1;
    }

    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations) {
        return long.class.isAssignableFrom(type) || Long.class.isAssignableFrom(type);
    }

    public void writeTo(Long l, Class<?> clazz, Type type, Annotation[] a, 
                        MediaType mt, MultivaluedMap<String, Object> headers, OutputStream os) 
        throws IOException {
        os.write(l.toString().getBytes());
        
    }

{code}

h3. Registering custom providers  


Putting @Provider annotation on the provider class is something that should lead to your provider being registered with the runtime. CXF does not support this feature yet. One can easily register a provider either from the Spring configuration :   

{code:xml}

Registering custom providers

Putting @Provider annotation on the provider class is something that should lead to your provider being registered with the runtime. CXF does not support this feature yet. One can easily register a provider either from the Spring configuration :

Code Block
xml
xml

<beans>
<jaxrs:server id="customerService" address="/">
    <jaxrs:serviceBeans>
      <bean class="org.CustomerService" />
    </jaxrs:serviceBeans>

    <jaxrs:entityProviders>
      <bean ref="isProvider" />
      <bean ref="longProvider" />
    </jaxrs:entityProviders>
    <bean id="isProvider" class="com.bar.providers.InputStreamProvider"/>
    <bean id="longProvider" class="com.bar.providers.LongProvider"/>
</jaxrs:server>
</beans>

Please

...

note

...

that

...

once

...

CXF

...

is

...

updated

...

to

...

support

...

a

...

0.7

...

version

...

of

...

JAX-RS

...

api,

...

<jaxrs:entityProviders>

...

will

...

be

...

changed

...

to

...

<jaxrs:providers>.

...

JAX-RS

...

supports

...

different

...

types

...

of

...

providers

...

and

...

having

...

a

...

single

...

<jaxrs:providers>

...

container

...

is

...

in

...

line

...

with

...

the

...

way

...

other

...

JAX-RS

...

implementations

...

discover

...

providers

...

by

...

checking

...

for

...

@Provider

...

annotations

...

only.

...

See

...

below

...

a

...

more

...

complete

...

beans.xml

...

definition.

Content type negotiation

One of the coolest thing of REST is that the same resource can be served using multiple representations. @ProduceMime and @ConsumeMime annotations are used to declare the supported request and response media types.

JAXB support

The request and response can be marshaled and unmarshaled to/from Java object using JAXB. The Java object needs to be marked with @XmlRootElement annotation. For example:

Code Block
java
java


{code}

h2. Content type negotiation

One of the coolest thing of REST is that the same resource can be served using multiple representations. @ProduceMime and @ConsumeMime annotations are used to declare the supported request and response media types. 


h3. JAXB support

The request and response can be marshaled and unmarshaled to/from Java object using JAXB. The Java object needs to be marked with @XmlRootElement annotation. For example:
{code:java}
@XmlRootElement(name = "Customer")
public class Customer {
    private String name;
    private long id;

    public Customer() {
    }

    public void setName(String n) {
        name = n;
    }

    public String getName() {
        return name;
    }

    public void setId(long i) {
        id = i;
    }

    public long getId() {
        return id;
    }

}
{code}

In

...

the

...

example

...

below,

...

the

...

Customer

...

object

...

returned

...

by

...

getCustomer

...

is

...

marshaled

...

using

...

JAXB

...

data

...

binding:

Code Block
java
java

{code:java}
@Path("/customerservice/")
public class CustomerService {
    @GET
    @Path("/customers/{customerId}/")
    public Customer getCustomer(@PathParam("customerId") String id) {
        ....
    }
}
{code}

The

...

wire

...

representation

...

of

...

Customer

...

object

...

is:

Code Block
java
java

{code:java}
@Path("/customerservice/")
<Customer>
    <id>123</id>
    <name>John</name>
</Customer>
{code}

To

...

work

...

with

...

collections,

...

you

...

need

...

to

...

define

...

an

...

object

...

collection

...

type.

...

For

...

example:

{
Code Block
}
@XmlRootElement(name = "Customers")
public class Customers {
    private Collection<Customer> customers;

    public Collection<Customer> getCustomer() {
        return customers;
    }

    public void setCustomer(Collection<Customer> c) {
        this.customers = c;
    }
}
@Path("/customerservice/")
public class CustomerService {
    @GET
    @Path("/customers/")
    public Customers getCustomers() {
        ....
    }
}
{code}

JSON support

Following code returns a Customer object that is marshaled to JSON format:

Code Block


h3. JSON support

Following code returns a Customer object that is marshaled to JSON format:
{code}
@Path("/customerservice/")
public class CustomerService {
    @ProduceMime("application/json")
    @GET
    @Path("/customers/{customerId}/")
    public Customer getCustomer(@PathParam("customerId") String id) {
        ....
    }
{code}

The

...

wire

...

representation

...

of

...

Customer

...

object

...

is:

Code Block
java
java

{code:java}
{"Customer ":{"id":"123","name":"john"}}

Source support

You can also receive the request as a Source object or return a Source object as response:

Code Block
java
java
{code}

h3. Source support

You can also receive the request as a Source object or return a Source object as response:

{code:java}
@Path("/customerservice/")
public class CustomerService {
    @PUT
    @Path("/customers/")
    public javax.xml.transform.Source updateCustomer(javax.xml.transform.Source ds) {
        ....
    }
}
{code}

h2. Secure JAX-RS services

A demo called 

Advanced Content type negotiation

CXF provides a partial support for an advanced content type negotiation by handling If-Match headers and ETags in its JAX-RS Request implementation. Neither If-Modified-Since nor Vary headers are currently supported.

Secure JAX-RS services

A demo called samples\jax_rs\basic_https

...

shows

...

you

...

how

...

to

...

do

...

communications

...

using

...

HTTPS.

...

Configuring JAX-RS

...

services

Configuring JAX-RS

...

services

...

programmatically

...

You

...

can

...

create

...

a

...

JAX-RS

...

RESTful

...

service

...

by

...

using

...

JAXRSServerFactoryBean

...

from

...

the

...

cxf-rt-frontend-jaxrs

...

package:

Code Block
java
java
 
{code:java}
JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
sf.setResourceClasses(CustomerService.class);
sf.setAddress("http://localhost:9000/");
sf.create();
{code}

A

...

couple

...

things

...

to

...

note:

...

  • The

...

  • JAXRSServerFactoryBean

...

  • creates

...

  • a

...

  • Server

...

  • inside

...

  • CXF

...

  • which

...

  • starts

...

  • listening

...

  • for

...

  • requests

...

  • on

...

  • the

...

  • URL

...

  • specified.

...

  • By

...

  • default,

...

  • the

...

  • JAX-RS

...

  • runtime

...

  • is

...

  • responsible

...

  • for

...

  • the

...

  • lifecycle

...

  • of

...

  • resource

...

  • classes,

...

  • default

...

  • lifecycle

...

  • is

...

  • per-request.

...

  • You

...

  • can

...

  • set

...

  • the

...

  • lifecycle

...

  • to

...

  • singleton

...

  • by

...

  • using

...

  • following

...

  • line:

...

  • Code Block
    java
    java
    
    sf.setResourceProvider(BookStore.class, new SingletonResourceProvider());
    

...

  • If you prefer not to let the JAX-RS

...

  • runtime

...

  • to

...

  • handle

...

  • the

...

  • resource

...

  • class

...

  • lifecycle

...

  • for

...

  • you

...

  • (for

...

  • example,

...

  • it

...

  • might

...

  • be

...

  • the

...

  • case

...

  • that

...

  • your

...

  • resource

...

  • class

...

  • is

...

  • created

...

  • by

...

  • other

...

  • containers

...

  • such

...

  • as

...

  • Spring),

...

  • you

...

  • can

...

  • do

...

  • following:

...

  • Code Block
    java
    java
    
    JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
    CustomerService cs = new CustomerService();
    sf.setServiceBeans(cs);
    sf.setAddress("http://localhost:9080/");
    sf.create();
    

...

Configuring JAX-RS

...

services

...

in

...

container

...

with

...

Spring

...

configuration

...

file.

...

web.xml

Code Block
xml
xml


{code:xml}
<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>WEB-INF/beans.xml</param-value>
	</context-param>

	<listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>

	<servlet>
		<servlet-name>CXFServlet</servlet-name>
		<display-name>CXF Servlet</display-name>
		<servlet-class>
			org.apache.cxf.transport.servlet.CXFServlet
		</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>CXFServlet</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
</web-app>

beans.xml

Code Block
xml
xml
{code}

h3. beans.xml

{code:xml}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:jaxrs="http://cxf.apache.org/jaxrs"
  xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">

  <import resource="classpath:META-INF/cxf/cxf.xml" />
  <import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml" />
  <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

  <jaxrs:server id="customerService" address="/">
    <jaxrs:serviceBeans>
      <bean<ref refbean="customerService" />
    </jaxrs:serviceBeans>
  </jaxrs:server>

  <bean id="customerService" class="demo.jaxrs.server.CustomerService" />
</beans>
{code}


h2. Combining 

Combining JAX-WS

...

and

...

JAX-RS

...

Here's

...

a

...

beans.xml

...

showing

...

how

...

to

...

have

...

a

...

single

...

service

...

class

...

supporting

...

both

...

SOAP

...

and

...

REST-based

...

invocations

...

at

...

the

...

same

...

time

...

with

...

the

...

help

...

of

...

JAX-WS

...

and

...

JAX-RS

...

:

Code Block
xml
xml
 

{code:xml}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:jaxrs="http://cxf.apache.org/jaxrs"
  xmlns:jaxws="http://cxf.apache.org/jaxws"
  xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">

  <import resource="classpath:META-INF/cxf/cxf.xml" />
  <import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml" />
  <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

  <!-- JAX-RS -->
  <jaxrs:server id="customerService" address="/">
    <jaxrs:serviceBeans>
      <bean<ref refbean="#customerServicecustomerService" />
    </jaxrs:serviceBeans>
  </jaxrs:server>

  <!-- JAX-WS -->
  <jaxws:endpoint implementor="#customerService"
    address="/CustomerWorld" wsdlLocation="..."/>
  
  <bean id="customerService" class="demo.jaxrs.server.CustomerService" />
</beans>
{code}

If

...

demo.jaxrs.server.CustomerService

...

was

...

used

...

to

...

serve

...

SOAP

...

requests

...

then

...

either

...

contract-first

...

or

...

Java-first

...

could've

...

been

...

used.

...

JAX-RS

...

annotations

...

can

...

be

...

added

...

to

...

the

...

existing

...

service

...

class.

...

Some

...

custome

...

providers

...

may

...

need

...

to

...

be

...

created,

...

depending

...

on

...

the

...

complexity

...

of

...

the

...

method

...

signatures.

...

When

...

a

...

WSDL-first

...

approach

...

is

...

used

...

then

...

a

...

document-literal-wrapped

...

style

...

may

...

or

...

may

...

not

...

be

...

z

...

good

...

fit

...

as

...

the

...

code

...

generator

...

unwraps

...

all

...

the

...

types

...

into

...

a

...

signature,

...

for

...

example

...

:

Code Block
java
java


{code:java}
public class CustomerService {
   void doIt(String a, String b) {...};
}
{code}  

By default 

By default JAX-RS

...

may

...

not

...

be

...

able

...

to

...

handle

...

such

...

methods

...

as

...

it

...

requires

...

that

...

only

...

a

...

single

...

parameter

...

can

...

be

...

available

...

in

...

a

...

signature

...

that

...

is

...

not

...

annotated

...

by

...

one

...

of

...

the

...

JAX-RS

...

annotations

...

like

...

@PathParam.

...

So

...

if

...


a

...

'String

...

a'

...

parameter

...

can

...

be

...

mapped

...

to

...

a

...

@Path

...

template

...

variable

...

or

...

one

...

of

...

the

...

query

...

segments

...

then

...

this

...

signature

...

won't

...

need

...

to

...

be

...

changed

...

:

Code Block
java
java


{code:java}
@Path("/customers/{a}")
public class CustomerService {
   void doIt(@PathParam("a") String a, String b) {...};
}
{code}  

For methods returning 

For methods returning 'void',

...

a

...

simple

...

custom

...

provider

...

can

...

be

...

created

...

which

...

will

...

basically

...

be

...

a

...

no-op

...

implementation.

JAX-RS and Spring AOP

CXF JAX-RS is capable of working with AOP interceptors applied to resource classes from Spring.
For example :

Code Block
xml
xml


<beans xsi:schemaLocation=" http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>

  <jaxrs:server id="bookservice" address="/">
	<jaxrs:serviceBeans>
          <ref bean="bookstore"/>
          <ref bean="bookstoreInterface"/>
        </jaxrs:serviceBeans>
   </jaxrs:server>
   <bean id="bookstore" class="org.apache.cxf.systest.jaxrs.BookStore"/>
   <bean id="bookstoreInterface" class="org.apache.cxf.systest.jaxrs.BookStoreWithInterface"/>

   <aop:config>
	<aop:aspect id="loggingAspect" ref="simpleLogger">
          <aop:before method="logBefore" pointcut="execution(* org.apache.cxf.systest.jaxrs.BookStore*.*(..))"/>
          <aop:after-returning method="logAfter" pointcut="execution(* org.apache.cxf.systest.jaxrs.BookStore*.*(..))"/>
        </aop:aspect>
   </aop:config>
   <bean id="simpleLogger" class="org.apache.cxf.systest.jaxrs.SimpleLoggingAspect"/>
</beans>

Note that some AOP configuration is applied to two JAX-RS resource classes. By default Spring uses JDK dynamic proxies every time a class to be proxified implements at least one interface or CGLIB proxies otherwise.

For example, here's how org.apache.cxf.systest.jaxrs.BookStoreWithInterface looks like :

Code Block
java
java


public interface BookInterface {
    @GET
    @Path("/thosebooks/{bookId}/")
    @ProduceMime("application/xml")
    Book getThatBook(Long id) throws BookNotFoundFault;
}

public class BookStoreWithInterface extends BookStoreStorage implements BookInterface {

    public Book getThatBook(@PathParam("bookId") Long id) throws BookNotFoundFault {
        return doGetBook(id);
    }

    @Path("/thebook")
    public Book getTheBook(@PathParam("bookId") Long id) throws BookNotFoundFault {
        return doGetBook(id);
    }
}

In this case Spring will use a JDK proxy to wrap a BookStoreWithInterface class. As such it is important that a method which needs to be invoked such as getThatBook(...) is part of the interface.

The other method, getTheBook() can not be dispatched to by a JAX-RS runtime as it's not possible to discover it through a JDK proxy. If this method also needs to be invoked then this method should either be added to the interface or CGLIB proxies have to be explicitly enabled (consult Spring AOP documentation for more details)

Areas for improvement and TODO list.