The server method returns a JAXBObject, the expected status code is 400 and
the ResponseExceptionHandler is not applicable as the method does not
declare any exceptions.
I think that either I have missed configure the intercepters or the custom
fault handler is not correct, i.e. writing to the HTTPResponse outputStream
instead of something cxf (see AbstractCustomFaultInterceptor below).
Here is the code:
bridge.war
cxf/spring config:
<jaxrs:server id="wsBridgeServer" address="/">
<jaxrs:serviceBeans>
<bean
class="uk.co.company.bridge.service.rest.RestSearchService"
p:searchServiceClient-ref="externalSearchService"/>
</jaxrs:serviceBeans>
<jaxrs:extensionMappings>
<entry key="xml" value="application/xml" />
</jaxrs:extensionMappings>
<jaxrs:features>
<cxf:logging/>
</jaxrs:features>
<jaxrs:dataBinding>
<bean class="org.apache.cxf.jaxb.JAXBDataBinding">
<property name="namespaceMap">
<map>
<entry
key="http://purl.org/dc/terms/" value="dc" />
<entry
key="http://schema.company.co.uk/production/1" value="" />
</map>
</property>
</bean>
</jaxrs:dataBinding>
<jaxrs:outFaultInterceptors>
<bean
class="uk.co.company.protocol.rest.interceptor.CustomOutFaultInterceptor"
p:errorResponseProvider-ref="bridgeErrorResponseProvider" />
</jaxrs:outFaultInterceptors>
<jaxrs:providers>
<bean
class="uk.co.company.protocol.rest.provider.CustomWebApplicationExceptionMapper"
p:errorResponseProvider-ref="bridgeErrorResponseProvider" />
</jaxrs:providers>
<jaxrs:outInterceptors>
<bean
class="uk.co.company.protocol.service.rest.interceptor.NoCacheRequestInterceptor"
/>
</jaxrs:outInterceptors>
</jaxrs:server>
<bean id="externalSearchServiceClientFactory"
class="uk.co.company.protocol.service.ClientFactory"
p:service="uk.co.company.search.service.ExternalSearchService"
p:serviceUri="${protocol.service.location.search}"/>
<!-- getClient() return (T)JAXRSClientFactory.create(serviceUri,
service)
-->
<bean id="externalSearchService"
factory-bean="externalSearchServiceClientFactory" factory-method="getClient"
/>
search-client:
@Path("/search")
public interface ExternalSearchService {
@GET
@Path("{count}/{offset}")
@Produces({APPLICATION_XML})
SearchResultsElement search(@PathParam("count") int count,
@PathParam("offset") int offset, @QueryParam("q") String searchTerm);
}
search.war
cxf/spring config:
<jaxrs:server id="wsSearchServer" address="/">
<jaxrs:serviceBeans>
<bean
class="uk.co.company.search.service.rest.RestSearchService" />
</jaxrs:serviceBeans>
<jaxrs:extensionMappings>
<entry key="xml" value="application/xml" />
</jaxrs:extensionMappings>
<jaxrs:dataBinding >
<bean class="org.apache.cxf.jaxb.JAXBDataBinding">
<property name="namespaceMap">
<map>
<entry>
<key>
<value>http://purl.org/dc/terms/</value>
</key>
<value>dc</value>
</entry>
<entry>
<key>
<value>http://schema.company.co.uk/production/1</value>
</key>
<value></value>
</entry>
</map>
</property>
</bean>
</jaxrs:dataBinding>
<jaxrs:features>
<cxf:logging/>
</jaxrs:features>
<jaxrs:outFaultInterceptors>
<bean
class="uk.co.company.protocol.rest.interceptor.CustomOutFaultInterceptor"
p:errorResponseProvider-ref="searchErrorResponseProvider" />
</jaxrs:outFaultInterceptors>
<jaxrs:providers>
<bean
class="uk.co.company.protocol.rest.provider.CustomWebApplicationExceptionMapper"
p:errorResponseProvider-ref="searchErrorResponseProvider" />
</jaxrs:providers>
</jaxrs:server>
bridgeErrorResponseProvider & searchErrorResponseProvider beans are
exception : status code mapping instances.
CustomOutFaultInterceptor is an instance of:
public class AbstractCustomFaultInterceptor extends
AbstractPhaseInterceptor<Message> {
...
public AbstractCustomFaultInterceptor() {
this(PRE_STREAM);
}
public AbstractCustomFaultInterceptor(String s) {
super(MARSHAL);
}
public void handleMessage(Message message) throws Fault {
handleMessageCalled = true;
Fault fault = (Fault)
message.getContent(Exception.class);
final ErrorElement error =
errorResponseProvider.create(fault.getCause());
/*
* ErrorElement JAXB object with String fields
statusCode & message. This
is want I expect/want to be in Response#getEntity()
* If the services are called directly for negative
path then the
ErrorElement is marshalled to the expected xml. I presume that
* this is due to the client being a WebClient and not
a ClientProxyImpl.
*/
final HttpServletResponse response =
(HttpServletResponse)
message.getExchange().getInMessage().get(
HTTP_RESPONSE);
response.setStatus(INTERNAL_SERVER_ERROR.getStatusCode());
response.setContentType(APPLICATION_XML);
try {
final byte[] errorElement = getResponse(error);
final OutputStream os =
response.getOutputStream();
os.write(errorElement);
os.flush();
message.getInterceptorChain().abort();
} catch (IOException ioex) {
throw new RuntimeException("Error writing the
response");
}
}
}
Sergey Beryozkin-5 wrote:
>
> Hi
>
> I'm not quite sure what error you're seeing.
> If an HTTP response status is >= 400 then, unless a given proxy method
> explicitly returns Response, WebApplicationException will be thrown (or a
> custom one provided ResponseExceptionHandler is registered). If an
> exception
> is thrown then one can still get a Response using
> WebClient.client(proxy).getResponse.
>
> Response.getEntity() will return an error InputStream. What is not clear
> is
> how a custom provider (DataBindingProvider) ends up tryng to deserialize
> such a Response, it should not happen.
>
> Can you post some code please ?
> cheers, Sergey
>
> On Wed, Mar 24, 2010 at 5:36 AM, tandem <[email protected]> wrote:
>
>>
>> I am talk between to jaxrs services in one tomcat and the happy path is
>> working as expected. Upon error I am getting back an InputStream (i.e.
>> sun.net.www.protocol.http.HttpURLConnection$HttpInputStream) from
>> Response#getEntity() and originally before trying many different
>> approaches
>> I was getting a marshaling issue (Marshalling Error: class
>> sun.net.www.protocol.http.HttpURLConnection$HttpInputStream nor any of
>> its
>> super class is known to this context) in the DataBindingProvider.
>> Obviously
>> the error makes sense but I am not sure what I have missed or if I simply
>> should just catch the exception and the read the stream (which I am not
>> entirely sure what to do with it once I have read it).
>>
>> Please let me know if some code will help explain the situation more.
>> --
>> View this message in context:
>> http://old.nabble.com/JAXRSClientFactory-proxy-error-handling-tp28010855p28010855.html
>> Sent from the cxf-user mailing list archive at Nabble.com.
>>
>>
>
>
--
View this message in context:
http://old.nabble.com/JAXRSClientFactory-proxy-error-handling-tp28010855p28015729.html
Sent from the cxf-user mailing list archive at Nabble.com.