On 16/10/14 22:12, Curtis Garman wrote:
Hmm...so I guess what I'm looking for is a way to define a sort of global
way to map status codes to exceptions so that I don't need to duplicate my
same try/catch logic around every client call. Aside from the
ResponseExceptionMapper, is there any way to do this for WebClient?
WebClient (and JAX-RS 2.0 Client/WebTarget implementation that delegates
to WebClient internally) is HTTP-centric API, you can use the methods
returning JAX-RS Response and react to statuses or deal with HTTP
centric exceptions defined in the spec API that WebClient will throw for
error statuses. It is there for users who are happy with doing the
HTTP-centric client programming.
Updating WebClient to map the HTTP statuses to custom Exceptions would
introduce the ambiguity into the WebClient model of doing HTTP calls and
would also imply that most of its methods would have to declare checked
Exception which would not be cool at all.
Why don't you use a proxy API if you'd like the statuses mapped to
custom exceptions; proxy API is there to 'shield' users from the
lower-level HTTP details
Sergey
-----Original Message-----
From: Sergey Beryozkin [mailto:[email protected]]
Sent: Thursday, October 16, 2014 11:23 AM
To: [email protected]
Subject: Re: Trouble configuring custom ResponseExceptionMapper
On 16/10/14 17:04, Curtis Garman wrote:
I did a little debugging and have discovered that
org.apache.cxf.jaxrs.client.WebClient does not seem to look for a
ResponseExceptionMapper. The doInvoke() method (around line 885)
simply looks at the response status returned and throws an error for
status > 300.
However, the org.apache.cxf.jaxrs.client. ClientProxyImpl has a
checkResponse method that actually checks for a custom mapper. The doc
seems to make me think that whether I'm using the WebClient or a
proxy, I should be able to deal with exceptions in the same way. Is
this supposed to be true?
WebClient is not supposed to deal with ResponseExceptionMapper - its purpose
is to facilitate the optional mapping of HTTP errors to Exception classes
listed in proxy method signatures
Sergey
-----Original Message-----
From: Sergey Beryozkin [mailto:[email protected]]
Sent: Wednesday, October 15, 2014 4:06 PM
To: [email protected]
Subject: Re: Trouble configuring custom ResponseExceptionMapper
I'll double check tomorrow, but I believe we have the tests involving
ResponseExceptionMapper, the conversion to default exceptions only
happens if no matching ResponseExceptionMapper has been detected...
Looks like a registration issue too... Any chance you can provide a
test case or may be debug into it ?
Cheers, Sergey
On 15/10/14 17:39, Curtis Garman wrote:
I have a java 8, Spring 4.1.1, cxf 3.0.1 app where I am tring to
implement a custom ResponseExceptionMapper for all exceptions
returned to my rest client. When I start my application, everything
starts fine. However even when I start the app with DEBUG logging
turned on, I see nothing related to my exception mapper. To test the
functionality, I am passing invalid creds to the rest service I'm
consuming. According to my mapper, the 403 response should be
converted to a custom AuthorizationException...however as can be seen
from
my log, the 403 is being converted to a jaxrs ForbiddenException.
Can anyone help me get things wired correctly? I noticed some of the
interfaces changed between cxf 2.x and 3.x. Is there a different
interface that I should be implementing? Implementing ExceptionMapper
on the service provider side works just fine.
package test.webservice.rest.exception;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import org.apache.cxf.jaxrs.client.ResponseExceptionMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Provider
@Component("exceptionMapper")
public class CustomResponseExceptionMapper implements
ResponseExceptionMapper<Exception> {
private static final Logger LOGGER =
LoggerFactory.getLogger(CustomResponseExceptionMapper.class);
@Override
public Exception fromResponse(Response response) {
LOGGER.debug(String.format("Executing %s",
CustomResponseExceptionMapper.class));
Response.Status status =
Response.Status.fromStatusCode(response.getStatus());
LOGGER.debug(String.format("Status: %s",
status.getStatusCode()));
switch (status) {
case BAD_REQUEST:
throw new
InvalidInputException(response.getHeaderString("exception"));
case UNAUTHORIZED:
throw new
AuthorizationException(response.getHeaderString("exception"));
case FORBIDDEN:
throw new
AuthorizationException(response.getHeaderString("exception"));
case NOT_FOUND:
throw new
EmptyResultDataAccessException(response.getHeaderString("exception"))
;
case CONFLICT:
throw new
DuplicateKeyException(response.getHeaderString("exception"));
default:
throw new
WebApplicationException(response.getHeaderString("exception"));
}
}
}
<?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:context="http://www.springframework.org/schema/context"
xmlns:cxf="http://cxf.apache.org/core"
xmlns:jaxrs-client="http://cxf.apache.org/jaxrs-client"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://cxf.apache.org/core
http://cxf.apache.org/schemas/core.xsd
http://cxf.apache.org/jaxrs-client
http://cxf.apache.org/schemas/jaxrs-client.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import
resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<bean id="jsonProvider"
class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>
<jaxrs-client:client id="albumClient"
serviceClass="org.apache.cxf.jaxrs.client.WebClient"
address="http://localhost:8080/rest-provider/services/album"
username="test"
password="test">
<jaxrs-client:headers>
<entry key="Accept"
value="application/xml"/>
</jaxrs-client:headers>
<jaxrs-client:providers>
<ref
bean="requestFilter" />
<ref bean="jsonProvider" />
<ref bean="responseFilter" />
<ref
bean="exceptionMapper"
/>
</jaxrs-client:providers>
</jaxrs-client:client>
<context:component-scan
base-package="test.webservice.rest.exception" />
<context:component-scan
base-package="test.webservice.rest.filter" />
<context:component-scan
base-package="test.webservice.rest.service" />
</beans>
HTTP Status 500 - Request processing failed; nested exception is
javax.ws.rs.ForbiddenException: HTTP 403 Forbidden
type Exception report
message Request processing failed; nested exception is
javax.ws.rs.ForbiddenException: HTTP 403 Forbidden
description The server encountered an internal error that prevented
it from fulfilling this request.
exception
org.springframework.web.util.NestedServletException: Request
processing failed; nested exception is javax.ws.rs.ForbiddenException:
HTTP 403 Forbidden
org.springframework.web.servlet.FrameworkServlet.processRequest(Frame
w
orkSer
vlet.java:973)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServl
e
t.java
:852)
javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkSer
v
let.ja
va:837)
javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
org.springframework.web.filter.ShallowEtagHeaderFilter.doFilterIntern
a
l(Shal
lowEtagHeaderFilter.java:81)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerR
e
questF
ilter.java:107)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52
)
root cause
javax.ws.rs.ForbiddenException: HTTP 403 Forbidden
sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown
Source)
java.lang.reflect.Constructor.newInstance(Unknown
Source)
org.apache.cxf.jaxrs.client.AbstractClient.convertToWebApplicationExc
e
ption(
AbstractClient.java:478)
org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:886)
org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:854)
org.apache.cxf.jaxrs.client.WebClient.invokeAndGetCollection(WebClient.java:
513)
org.apache.cxf.jaxrs.client.WebClient.getCollection(WebClient.java:58
9
)
test.webservice.rest.service.SimpleAlbumService.findAlbums(SimpleAlbu
m
Servic
e.java:28)
test.webservice.rest.servlet.AlbumController.list(AlbumController.jav
a
:27)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native
Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown
Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown
Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.web.method.support.InvocableHandlerMethod.invoke(
I
nvocab
leHandlerMethod.java:215)
org.springframework.web.method.support.InvocableHandlerMethod.invokeF
o
rReque
st(InvocableHandlerMethod.java:132)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocabl
e
Handle
rMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingH
a
ndlerA
dapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingH
a
ndlerA
dapter.handleInternal(RequestMappingHandlerAdapter.java:721)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapt
e
r.hand
le(AbstractHandlerMethodAdapter.java:83)
org.springframework.web.servlet.DispatcherServlet.doDispatch(Dispatch
e
rServl
et.java:943)
org.springframework.web.servlet.DispatcherServlet.doService(Dispatche
r
Servle
t.java:877)
org.springframework.web.servlet.FrameworkServlet.processRequest(Frame
w
orkSer
vlet.java:961)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServl
e
t.java
:852)
javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkSer
v
let.ja
va:837)
javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
org.springframework.web.filter.ShallowEtagHeaderFilter.doFilterIntern
a
l(Shal
lowEtagHeaderFilter.java:81)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerR
e
questF
ilter.java:107)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52
)