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 | ||||
---|---|---|---|---|
| ||||
{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 | ||||
---|---|---|---|---|
| ||||
{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 | ||||
---|---|---|---|---|
| ||||
InputStream is = message.getContent(InputStream.class); message.setContent(new MyFilterInputStream(is)); message.put(Message.ACCEPT_CONTENT_TYPE, "custom/media"); |
Code Block | ||||
---|---|---|---|---|
| ||||
{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 | ||||
---|---|---|---|---|
| ||||
{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
...
...
...
...
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 | ||||
---|---|---|---|---|
| ||||
{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 | ||||
---|---|---|---|---|
| ||||
{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 | ||||
---|---|---|---|---|
| ||||
{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 | ||||
---|---|---|---|---|
| ||||
{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 | ||||
---|---|---|---|---|
| ||||
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
...
...
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 | ||||
---|---|---|---|---|
| ||||
{code:xml} <beans> <jaxrs:server address="/"> <jaxrs:invoker> <bean class="org.apache.cxf.systest.jaxrs.CustomJAXRSInvoker"/> </jaxrs:invoker> </jaxrs:server> </beans> {code} |