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.

Reply via email to