Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

unmigrated-inline-wiki-markup
{span:style=font-size:2em;font-weight:bold} JAX-RS Filters {span}

...

Table of Contents

Filters

Often it's

...

necessary

...

to

...

pre-

...

or

...

post-process

...

some

...

requests

...

according

...

to

...

a

...

number

...

of

...

requirements.

...


For

...

example,

...

a

...

request

...

like

...

GET

...

/resource?_type=xml

...

is

...

supported

...

by

...

a

...

CXF

...

specific

...

RequestHandler

...

filter

...

which

...

modifies

...

the

...

CXF

...

input

...

Message

...


by

...

updating

...

one

...

of

...

its

...

headers.

...

In

...

some

...

cases

...

users

...

can

...

use

...

the

...

existing

...

filter

...

technologies

...

such

...

as

...

Servler

...

filters

...

or

...

Spring

...

AOP

...

proxies.

...

In

...

other

...

cases,

...

it

...

can

...

be

...

handy

...


to

...

write

...

a

...

CXF

...

filter

...

which

...

will

...

introspect

...

the

...

resource

...

class,

...

input

...

or

...

output

...

message,

...

the

...

operation

...

which

...

was

...

invoked

...

and

...

modify

...

the

...

request

...

or

...

response

...

accordingly.

...

Here

...

are

...

the

...

interface

...

definitions

...

:

Code Block
java
java
 

{code:java}
import org.apache.cxf.jaxrs.ext.RequestHandler;
import org.apache.cxf.jaxrs.model.ClassResourceInfo;
import org.apache.cxf.message.Message;

public interface RequestHandler {
    
    Response handleRequest(Message inputMessage, 
                           ClassResourceInfo resourceClass);

}
{code}

The

...

request

...

handler

...

implementation

...

can

...

either

...

modify

...

the

...

input

...

Message

...

and

...

let

...

the

...

request

...

to

...

proceed

...

or

...

block

...

the

...

request

...

by

...

returning

...

a

...

non-null

...

Response.

...

A

...

response

...

filter

...

implementation

...

can

...

get

...

an

...

access

...

to

...

OperationResourceInfo

...

object

...

representing

...

a

...

method

...

to

...

be

...

invoked

...

on

...

a

...

resource

...

class

...

:

Code Block
java
java


{code:java}
OperationResourceInfo ori = exchange.get(OperationResourceInfo.class);
{code}  

Use OperationResourceInfo in your filter with care. In principle a given request chain may have filters which may want to  overwrite Accept or ContentType message headers which might lead to another method be selected. However if you know no such filters (will) exist in your application then you might want to check an OperationResourceInfo instance as part of your filter logic. 

When modifying an input message, one would typically want to replace a message input stream or one of its headers, such as ContentType :
{code:java}

Use OperationResourceInfo in your filter with care. In principle a given request chain may have filters which may want to overwrite Accept or ContentType message headers which might lead to another method be selected. However if you know no such filters (will) exist in your application then you might want to check an OperationResourceInfo instance as part of your filter logic.

When modifying an input message, one would typically want to replace a message input stream or one of its headers, such as ContentType :

Code Block
java
java
InputStream is = message.getContent(InputStream.class);
message.setContent(new MyFilterInputStream(is));
message.put(Message.ACCEPT_CONTENT_TYPE, "custom/media"); 
Code Block
java
java
{code}

{code:java}
import javax.ws.rs.core.Response;
import org.apache.cxf.jaxrs.ext.ResponseHandler;
import org.apache.cxf.jaxrs.model.OperationResourceInfo
import org.apache.cxf.message.Message;

public interface ResponseHandler {
    
    Response handleResponse(Message outputMessage,
                           OperationResourceInfo invokedOperation, 
                           Response response);

}
{code}

The

...

response

...

handler

...

implementation

...

can

...

optionally

...

overwrite

...

or

...

modify

...

the

...

application

...

Response

...

or

...

modify

...

the

...

output

...

message.

...

When

...

modifying

...

an

...

output

...

message,

...

one

...

may

...

want

...

to

...

either

...

replace

...

an

...

output

...

stream

...

before

...

message

...

body

...

providers

...

attempt

...

to

...

write

...

to

...

it

...

or

...

replace

...

the

...

actual

...

response

...

object

...

:

Code Block
java
java

{code:java}
// replace an output stream
OutputStream os = message.getContent(OutputStream.class);
message.setContent(new MyFilterOutputStream(os));

// replace an actual object
response.setEntity(new MyWrapper(response.getEntity()))
// or using a low-level Message api if needed
MessageContentsList objs = MessageContentsList.getContentsList(message);
if (objs !== null && objs.size() == 1) {
    Object responseObj = objs.remove(0);
    obj.add(new MyWrapper(responseObj));
}
{code}

Please

...

see

...

this

...

blog

...

entry

...

for

...

another

...

example

...

of

...

when

...

response

...

filters

...

can

...

be

...

useful.

...

Multiple

...

request

...

and

...

response

...

handlers

...

are

...

supported.

...

The

...

implementations

...

can

...

be

...

registered

...

like

...

any

...

other

...

types

...

of

...

providers

...

:

Code Block
xml
xml


{code:xml}

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

    <jaxrs:providers>
      <ref bean="authorizationFilter" />
    </jaxrs:providers>
    <bean id="authorizationFilter" class="com.bar.providers.AuthorizationRequestHandler">
        <!-- authorization bean properties -->
    </bean>
</jaxrs:server>
</beans>
{code}

h2. Difference between JAXRS filters and CXF interceptors

JAXRS runtime flow is mainly implemented by a pair of 'classical' CXF interceptors. JAXRSInInterceptor is currently at Phase.UNMARSHAL (was at 

Difference between JAXRS filters and CXF interceptors

JAXRS runtime flow is mainly implemented by a pair of 'classical' CXF interceptors. JAXRSInInterceptor is currently at Phase.UNMARSHAL (was at Phase.PRE_STREAM

...

before

...

CXF

...

2.2.2)

...

phase

...

while

...

JAXRSOutInterceptor

...

is

...

currently

...

at

...

Phase.MARSHAL

...

phase.

...

JAXRS

...

filters

...

can

...

be

...

thought

...

of

...

as

...

additional

...

handlers.

...

JAXRSInInterceptor

...

deals

...

with

...

a

...

chain

...

of

...

RequestHandlers,

...

just

...

before

...

the

...

invocation.

...

JAXRSOutInterceptor

...

deals

...

with

...

a

...

chain

...

of

...

ResponseHandlers,

...

just

...

after

...

the

...

invocation

...

but

...

before

...

message

...

body

...

writers

...

get

...

their

...

chance.

...

Sometimes

...

you

...

may

...

want

...

to

...

use

...

CXF

...

interceptors

...

rather

...

than

...

writing

...

JAXRS

...

filters.

...

For

...

example,

...

suppose

...

you

...

combine

...

JAXWS

...

and

...

JAXRS

...

and

...

you

...

need

...

to

...

log

...

only

...

inbound

...

or

...

outbound

...

messages.

...

You

...

can

...

reuse

...

the

...

existing

...

CXF

...

interceptors

...

:

Code Block
xml
xml


{code:xml}
<beans>
<bean id="logInbound" class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
<bean id="logOutbound" class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>

<jaxrs:server> 
 <jaxrs:inInterceptors>
     <ref bean="logInbound"/>
 </jaxrs:inInterceptors>
 <jaxrs:outInterceptors>
    <ref bean="logOutbound"/>
 </jaxrs:outInterceptors>
</jaxrs:server>

<jaxws:endpoint>
 <jaxws:inInterceptors>
     <ref bean="logInbound"/>
 </jaxws:inInterceptors>
 <jaxws:outInterceptors>
    <ref bean="logOutbound"/>
 </jaxws:outInterceptors>
</jaxws:endpoint>

</beans>
{code} 

Reusing other CXF 

Reusing other CXF interceptors/features

...

such

...

as

...

GZIP

...

handlers

...

can

...

be

...

useful

...

too.

...

Overriding

...

request

...

and

...

response

...

properties

...

Now

...

and

...

then

...

one

...

needs

...

to

...

overwrite

...

various

...

request

...

and

...

response

...

properties

...

like

...

HTTP

...

method

...

or

...

request

...

URI,

...


response

...

headers

...

or

...

status

...

codes

...

and

...

even

...

the

...

request

...

or

...

response

...

body.

...

JAX-RS

...

Response

...

may

...

be

...

used

...

to

...

specify

...

custom

...

status

...

and

...

response

...

headers

...

but

...

it

...

might

...

be

...

intrusive

...

to

...

add

...

it

...

to

...

method

...

signatures.

...

Using

...

filters

...

and

...

interceptors

...

makes

...

it

...

possible

...

to

...

override

...

all

...

the

...

needed

...

request/response

...

properties.

...

Overriding HTTP method

Register a custom RequestHandler filter which will replace the current method value keyed by
Message.HTTP_REQUEST_METHOD

...

in

...

a

...

given

...

Message.

...

Overriding request URI,

...

query

...

and

...

headers

...

One

...

can

...

do

...

it

...

either

...

from

...

a

...

CXF

...

input

...

interceptor

...

(registered

...

at

...

the

...

early

...

phase

...

like

...

USER_STREAM)

...

or

...

from

...

a

...

RequestHandler

...

filter,

...

for

...

example

...

:

Code Block
java
java


{code:java}
String s = m.get(Message.REQUEST_URI);
s += "/data/";
m.put(Message.REQUEST_URI, s);
{code} 

If the updated Request URI has a new query string, then you also need to update a 

If the updated Request URI has a new query string, then you also need to update a Message.QUERY_STRING

...

property.

...

Similarly,

...

one

...

can

...

update

...

request

...

HTTP

...

headers,

...

by

...

modifying

...

a

...

Message.REQUEST_HEADERS

...

Message

...

object

...

which

...

is

...

a

...

Map

...

containing

...

String

...

and

...

List

...

of

...

Strings

...

entries.

...

Overriding

...

response

...

status

...

code

...

and

...

headers

...

It

...

is

...

assumed

...

here

...

a

...

user

...

prefers

...

not

...

to

...

use

...

explicit

...

Response

...

objects

...

in

...

the

...

application

...

code.

...


This

...

can

...

be

...

done

...

either

...

from

...

a

...

CXF

...

output

...

interceptor

...

(phase

...

like

...

MARSHALL

...

will

...

do)

...

or

...

from

...

a

...

ResponseHandler

...

filter,

...

for

...

example

...

this

...

code

...

will

...

work

...

for

...

both

...

JAXRS

...

and

...

JAXWS

...

:

Code Block
java
java


{code:java}
import java.util.Map;
import java.util.TreeMap;

import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;


public class CustomOutInterceptor extends AbstractOutDatabindingInterceptor {
    
    public CustomOutInterceptor() {
        super(Phase.MARSHAL);
    }

    public void handleMessage(Message outMessage) {
        Map<String, List<String>> headers = (Map<String, List<String>>)outMessage.get(Message.PROTOCOL_HEADERS);
        if (headers == null) {
            headers = new TreeMap<String, List<String>>(String.CASE_INSENSITIVE_ORDER);
            message.put(Message.PROTOCOL_HEADERS, headers);
        }
        // modify headers  
    }    
{code}  

At the moment it is not possible to override a response status code from a CXF interceptor running before JAXRSOutInterceptor, like CustomOutInterceptor above, which will be fixed.
The only option at the moment is to use a custom ResponseHandler which will replace the current Response object with another one containing the required status. 

h1. Ignoring JAXRS MessageBodyWriters

In some cases you may want to have a JAXRS Response entity which a given RequestHandler or ResponseHandler has produced to be directly written to the output stream. For example, a CXF JAXRS WADLGenerator RequestHandler produces an XML content which does not have to be serialized by JAXRS MessageBodyWriters. If you do need to have the writers ignored then set the following property on the current exchange in the custom handler :

{code:java}

At the moment it is not possible to override a response status code from a CXF interceptor running before JAXRSOutInterceptor, like CustomOutInterceptor above, which will be fixed.
The only option at the moment is to use a custom ResponseHandler which will replace the current Response object with another one containing the required status.

Ignoring JAXRS MessageBodyWriters

In some cases you may want to have a JAXRS Response entity which a given RequestHandler or ResponseHandler has produced to be directly written to the output stream. For example, a CXF JAXRS WADLGenerator RequestHandler produces an XML content which does not have to be serialized by JAXRS MessageBodyWriters. If you do need to have the writers ignored then set the following property on the current exchange in the custom handler :

Code Block
java
java
message.getExchange().put("ignore.message.writers", true);
{code}

h1. Custom invokers

*Note* This feature is available starting from CXF 

Custom invokers

Note This feature is available starting from CXF 2.2.2

...

Using

...

custom

...

JAXR-RS

...

invokers

...

is

...

yet

...

another

...

way

...

to

...

pre

...

or

...

post

...

process

...

a

...

given

...

invocation.

...

For

...

example,

...

this

...

invoker

...

does

...

a

...

security

...

check

...

before

...

delegating

...

to

...

the

...

default

...

JAXRS

...

invoker.

...

A

...

custom

...

invoker,

...

like

...

a

...

request

...

filter,

...

has

...

the

...

access

...

to

...

all

...

the

...

information

...

accumulated

...

during

...

the

...

processing

...

of

...

a

...

given

...

call,

...

but

...

additionally,

...

it

...

can

...

also

...

check

...

the

...

actual

...

method

...

parameter

...

values.

...

Custom

...

invokers

...

can

...

be

...

registered

...

like

...

this

...

:

Code Block
xml
xml


{code:xml}
<beans>

<jaxrs:server address="/"> 
 <jaxrs:invoker>
   <bean class="org.apache.cxf.systest.jaxrs.CustomJAXRSInvoker"/>
 </jaxrs:invoker>
</jaxrs:server>

</beans>
{code}