You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Juan José Pérez Consuegra <jj...@gmail.com> on 2012/10/05 11:09:15 UTC
Customize Response error to client using Invoker
Hello all,
I' trying to send a custom error message to client when a non authorization
intent has been detected. I'm using invoker to extract user and password
and I want to send back a Response or launch an Exception. If I use a
Response the received message in client is empty with status 200 OK.
And if I throw a webapplicationexception like this:
<ns1:XMLFault xmlns:ns1="http://cxf.apache.org/bindings/xformat"><ns1:faultstring
xmlns:ns1="http://cxf.apache.org/bindings/xformat
">javax.ws.rs.WebApplicationException</ns1:faultstring></ns1:XMLFault>
with server status 500.
Here is my code:
@Override
public Object invoke(Exchange exchange, Object requestParams, Object
resourceObject) throws WebApplicationException{
Message mensaje = exchange.getInMessage();
AuthorizationPolicy policy =
(AuthorizationPolicy)mensaje.get(AuthorizationPolicy.class);
if (policy == null) {
return Response.status(401).build();
// throw new
WebApplicationException(Response.status(401).build());
}
String retUsuario = policy.getUserName();
String retPassword = policy.getPassword();
if (autenticacionValida(retUsuario, retPassword)){
return super.invoke(exchange, requestParams, resourceObject);
} else {
return Response.status(401).build();
// throw new
WebApplicationException(Response.status(401).build());
}
}
May I use an exception mapper?? If so, How I must register the mapper, I
tryed to do that like this:
sf = new JAXRSServerFactoryBean();
sf.setResourceClasses(RLABSystemWSRest.class);
sf.setResourceProvider(RLABSystemWSRest.class,
new SingletonResourceProvider(new RLABSystemWSRest()));
sf.setAddress("http://localhost:9001/");
RestInvoker invoker = new RestInvoker();
RestExceptionMapper mapper = new RestExceptionMapper();
sf.setInvoker(invoker);
sf.setProvider(mapper);
server = sf.create();
with this code as mapper:
@Provider
public class RestExceptionMapper implements
ExceptionMapper<WebApplicationException> {
@Override
public Response toResponse(WebApplicationException ex) {
ResponseBuilder rb = Response.status(401);
return rb.build();
}
}
but it doesn't work.
I have another question, is about the stack trace in mi server console, I
would like it doesn't appear, or show a custom message too, when I return a
Response nothing happens of course, but when I throws a
webapplicationexception added to the result in client I have this in my
server:
Advertencia: Interceptor for {
http://ws.cserver.related.scc.uned.es/}RLABSystemWSRest has thrown
exception, unwinding now
javax.ws.rs.WebApplicationException
at
es.uned.scc.related.cserver.ws.RestInvoker.invoke(RestInvoker.java:23)
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:94)
at
org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58)
at
org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:94)
at
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
at
org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:122)
at
org.apache.cxf.transport.http_jetty.JettyHTTPDestination.serviceRequest(JettyHTTPDestination.java:344)
at
org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:310)
at
org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:72)
at
org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:227)
at
org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:941)
at
org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:188)
at
org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:875)
at
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
at
org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250)
at
org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149)
at org.eclipse.jetty.server.handler.HandlerWrapper.handl
.........
thanks in advance,
Juanjo
Re: Customize Response error to client using Invoker
Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
On 05/10/12 10:09, Juan José Pérez Consuegra wrote:
> Hello all,
>
> I' trying to send a custom error message to client when a non authorization
> intent has been detected. I'm using invoker to extract user and password
> and I want to send back a Response or launch an Exception. If I use a
> Response the received message in client is empty with status 200 OK.
>
> And if I throw a webapplicationexception like this:
>
>
> <ns1:XMLFault xmlns:ns1="http://cxf.apache.org/bindings/xformat"><ns1:faultstring
> xmlns:ns1="http://cxf.apache.org/bindings/xformat
> ">javax.ws.rs.WebApplicationException</ns1:faultstring></ns1:XMLFault>
>
> with server status 500.
>
>
> Here is my code:
> @Override
> public Object invoke(Exchange exchange, Object requestParams, Object
> resourceObject) throws WebApplicationException{
> Message mensaje = exchange.getInMessage();
> AuthorizationPolicy policy =
> (AuthorizationPolicy)mensaje.get(AuthorizationPolicy.class);
> if (policy == null) {
> return Response.status(401).build();
> // throw new
> WebApplicationException(Response.status(401).build());
> }
> String retUsuario = policy.getUserName();
> String retPassword = policy.getPassword();
> if (autenticacionValida(retUsuario, retPassword)){
> return super.invoke(exchange, requestParams, resourceObject);
> } else {
> return Response.status(401).build();
> // throw new
> WebApplicationException(Response.status(401).build());
> }
> }
I think using a custom invoker to enforce the authorization only makes
sense if the actual objects to be passed to the resource method can
provide some extra context - otherwise use a RequestHandler filter (or
preferably ContainerRequestFilter in CXF 2.7.0) - you can simply block a
request from there with a custom Response.
If you do need to use the invoker and decide to throw an exception:
this exception now escapes the JAX-RS 'catch' blocks which try to map it
to Response with the help of the registered mappers - and this is why
you see the above XML-formatted error message - in fact the exception
should've been propagated to the servlet layer - guess you configure the
endpoint not to propagate.
So, to manage the exceptions thrown from the invoker:
- register custom out fault interceptor - this one can write directly to
HTTP output stream if needed.
- do not throw the exception - create Response within your custom
invoker and 'return new MessageContentList(myResponse)'
>
> May I use an exception mapper?? If so, How I must register the mapper, I
> tryed to do that like this:
>
> sf = new JAXRSServerFactoryBean();
> sf.setResourceClasses(RLABSystemWSRest.class);
> sf.setResourceProvider(RLABSystemWSRest.class,
> new SingletonResourceProvider(new RLABSystemWSRest()));
> sf.setAddress("http://localhost:9001/");
> RestInvoker invoker = new RestInvoker();
> RestExceptionMapper mapper = new RestExceptionMapper();
> sf.setInvoker(invoker);
> sf.setProvider(mapper);
> server = sf.create();
>
> with this code as mapper:
>
> @Provider
> public class RestExceptionMapper implements
> ExceptionMapper<WebApplicationException> {
>
> @Override
> public Response toResponse(WebApplicationException ex) {
> ResponseBuilder rb = Response.status(401);
> return rb.build();
> }
>
> }
>
> but it doesn't work.
>
> I have another question, is about the stack trace in mi server console, I
> would like it doesn't appear, or show a custom message too, when I return a
> Response nothing happens of course, but when I throws a
> webapplicationexception added to the result in client I have this in my
> server:
>
Because the exception escapes, the CXF PhaseInterceptorChain prints this
stack trace by default - you can register CXF FaultListener that can
make it 'silent' - but you only need it if you decide to continue
throwing the exceptions from the invoker
Cheers, Sergey
> Advertencia: Interceptor for {
> http://ws.cserver.related.scc.uned.es/}RLABSystemWSRest has thrown
> exception, unwinding now
> javax.ws.rs.WebApplicationException
> at
> es.uned.scc.related.cserver.ws.RestInvoker.invoke(RestInvoker.java:23)
> at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:94)
> at
> org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58)
> at
> org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:94)
> at
> org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
> at
> org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:122)
> at
> org.apache.cxf.transport.http_jetty.JettyHTTPDestination.serviceRequest(JettyHTTPDestination.java:344)
> at
> org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:310)
> at
> org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:72)
> at
> org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:227)
> at
> org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:941)
> at
> org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:188)
> at
> org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:875)
> at
> org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
> at
> org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250)
> at
> org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149)
> at org.eclipse.jetty.server.handler.HandlerWrapper.handl
> .........
>
>
>
> thanks in advance,
>
> Juanjo
>
--
Sergey Beryozkin
Talend Community Coders
http://coders.talend.com/
Blog: http://sberyozkin.blogspot.com