Sergey,

 I was finally able to work through a  rest fault out interceptor by
extending on the hints you provided.
 It  can generate the right content for xml and json types set by the
client even if it was the interceptor upstream that threw an
exception.
To do so I had to do some more work. See the attached interceptor.

Regards,
Vinay

On Fri, Apr 15, 2011 at 6:02 AM, Vinay Chandrasekharan
<[email protected]> wrote:
> Hi
>
> Regards,
> Vinay Chandrasekharan
> On Apr 15, 2011, at 3:18 AM, Sergey Beryozkin <[email protected]> wrote:
>
> Hi
>
> On Thu, Apr 14, 2011 at 10:55 PM, Vinay Chandrasekharan <[email protected]>
> wrote:
>>
>> I used the second approach you had suggested.  I tried setting the content
>> type too explictly but in vain.
>
> So are you saying that it works if Accept is application/json but does not
> if accept is text/xml ? That is a bit strange.
> It's difficult to advise without seeing a testcase
>
> Yes that is exactly what is happening , therefore strange
>>
>> Btw , How do i use the request filter to solve?
>>
> If you the filter then all that conversion of exceptions will be done for
> you by the runtime, provided you have exception mappers available
>
> Let me go thru filter approach
>
> Cheers, Sergey
>
>>
>> Regards,
>> Vinay Chandrasekharan
>> On Apr 14, 2011, at 4:22 PM, Sergey Beryozkin <[email protected]>
>> wrote:
>>
>> it does not look like you set the content type there, by the way can you
>> use RequestHandler filter instead ?
>>
>> Cheers, Sergey
>>
>> On Thu, Apr 14, 2011 at 5:06 PM, Vinay Chandrasekharan
>> <[email protected]> wrote:
>>>
>>> Thanks Sergey.
>>> It worked like a charm for application/json content-types but its
>>> return 304 with no payload (obviously) for text/xml content types.
>>> Can you throw light as to what might be going on here?
>>> Here is the snippet based on what you had suggested.
>>>
>>>
>>> =========
>>> /**
>>>  * REST fault out interceptor that can send exceptions raised by the
>>>  * interceptor, if any, according to the Accept header set by the
>>> client(s)
>>>  *
>>>  * @author vinay
>>>  *
>>>  */
>>> public class RestFaultOutInterceptor extends JAXRSOutInterceptor {
>>>        private static final Logger LOG = LoggerFactory
>>>                        .getLogger(RestFaultOutInterceptor.class);
>>>
>>>        public RestFaultOutInterceptor() {
>>>                getBefore().add(LoggingOutInterceptor.class.getName());
>>>        }
>>>
>>>        public void handleMessage(Message message) {
>>>                Exception ex = message.getContent(Exception.class);
>>>                LOG.info("Got exception " + ex);
>>>                if (ex == null) {
>>>                        throw new RuntimeException("Exception is
>>> expected");
>>>                }
>>>                if (!(ex instanceof Fault)) {
>>>                        throw new RuntimeException("Fault is expected");
>>>                }
>>>                Exception cause = (Exception) ex.getCause();
>>>                Response response =
>>> JAXRSUtils.convertFaultToResponse(cause, message
>>>                                .getExchange().getInMessage());
>>>                message.setContent(List.class, new
>>> MessageContentsList(response));
>>>                super.handleMessage(message);
>>>                message.getInterceptorChain().abort();
>>>        }
>>> }
>>> ===============
>>>
>>> Regards,
>>> Vinay
>>>
>>> On Wed, Apr 13, 2011 at 10:58 AM, Sergey Beryozkin <[email protected]>
>>> wrote:
>>> > Hi
>>> >
>>> > On Wed, Apr 13, 2011 at 3:20 PM, vinayc <[email protected]> wrote:
>>> >>
>>> >> Hi,
>>> >>  I am using CXF 2.3.3, and I have a custom cxf "in" interceptor
>>> >> attached
>>> >> to
>>> >> a REST service.
>>> >> When this interceptor throws an exception, xmlfaultoutinterceptor is
>>> >> called.
>>> >>
>>> > Yes, that will happen if the exception is thrown from a CXF
>>> > interceptor,
>>> > outside of the JAX-RS scope...
>>> >
>>> >>
>>> >> Is there an existing cxf fault out interceptor that can format the
>>> >> message
>>> >> based on  the "Accept:" header set by the client since right now even
>>> >> if
>>> >> the
>>> >> caller is setting "application/json" type, it still returns an
>>> >> "text/xml"
>>> >> content back (since its XmlFaultOutIntereceptor that sends the fault
>>> >> back)?
>>> >>
>>> >
>>> > Can you try the following:
>>> > - add a custom out fault interceptor which will delegate internally to
>>> > an
>>> > instance of JAXRSOutInterceptor.handleMessage() and abort the current
>>> > out
>>> > fault chain afterwards ? Before delegating, it should probably do the
>>> > following:
>>> >
>>> > 1. Get the Exception from the message:
>>> > Exception ex = ((Fault)message.getContent(Exception.class)).getCause();
>>> >
>>> > 2. Next you need to wrap it in JAX-RS Response
>>> >
>>> > You can do it manually:
>>> >
>>> > Response r =
>>> >
>>> > Response.status(status).type("application/json").entity(exceptionObject).build();
>>> >
>>> >
>>> > or if you have ExceptionMappers then you can use this call:
>>> >
>>> > Response r = JAXRSUtils.convertFaultToResponse(ex,
>>> > message.getExchange().getInMessage());
>>> >
>>> > 3. Set Response on the message:
>>> >
>>> > message.setContent(List.class, new MessageContentList(r));
>>> >
>>> > 4. new JAXRSOutInterceptor.handleMessage(message);
>>> > 5. message.getInterceptorChain().abort();
>>> >
>>> > that may work
>>> > Cheers, Sergey
>>> >
>>> >>
>>> >> Thanks
>>> >>
>>> >> Regards,
>>> >> Vinay
>>> >>
>>> >> --
>>> >> View this message in context:
>>> >>
>>> >> http://cxf.547215.n5.nabble.com/Handling-exceptions-thrown-by-interceptors-for-rest-calls-tp4300713p4300713.html
>>> >> Sent from the cxf-user mailing list archive at Nabble.com.
>>> >
>>> >
>>>
>>>
>>>
>>> --
>>> Warm regards,
>>> Vinay Chandrasekharan
>>
>>
>>
>> --
>> Sergey Beryozkin
>>
>> Application Integration Division of Talend
>> http://sberyozkin.blogspot.com
>
>
>



-- 
Warm regards,
Vinay Chandrasekharan
package vinay.poc.jaxrs.interceptor;

import java.util.Iterator;
import java.util.List;

import javax.ws.rs.core.Response;

import org.apache.cxf.binding.xml.interceptor.XMLFaultOutInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.interceptor.StaxOutInterceptor;
import org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor;
import org.apache.cxf.jaxrs.utils.JAXRSUtils;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageContentsList;

/**
 * REST fault out interceptor that can send exceptions raised by the
 * interceptor, if any, according to the Accept header set by the client(s)
 * 
 * @author vinay
 * 
 */
public class RestFaultOutInterceptor extends JAXRSOutInterceptor {

	public RestFaultOutInterceptor() {
		getBefore().add(LoggingOutInterceptor.class.getName());
		// for xml, this downstream interceptor caused an exception- therefore
		// standing before it so that I can remove it from the chain
		getBefore().add(XMLFaultOutInterceptor.class.getName());
		// for json, this downstream interceptor caused an exception- therefore
		// standing before it so that I can remove it from the chain
		getBefore().add(
				StaxOutInterceptor.StaxOutEndingInterceptor.class.getName());

	}

	public void handleMessage(Message message) {
		Exception ex = message.getContent(Exception.class);

		if (ex == null) {
			throw new RuntimeException("Exception is expected");
		}
		if (!(ex instanceof Fault)) {
			throw new RuntimeException("Fault is expected");
		}
		Exception cause = (Exception) ex.getCause();
		Response response = JAXRSUtils.convertFaultToResponse(cause, message
				.getExchange().getInMessage());

		message.setContent(List.class, new MessageContentsList(response));

		// To avoid the null pointer from
		// JAXBElementProvider.getAttachments(...) , set out message on the
		// exchange
		message.getExchange().setOutMessage(
				message.getExchange().getOutFaultMessage());

		// let JAXRSOutInterceptor do the serialization
		super.handleMessage(message);

		// remove 2 culprits from the chain so as to use logging or other
		// interceptors downstrean
		Iterator<Interceptor<? extends Message>> chainIterator = message
				.getInterceptorChain().iterator();
		while (chainIterator.hasNext()) {
			Interceptor<? extends Message> interceptor = chainIterator.next();
			// removing for xml
			if (interceptor instanceof XMLFaultOutInterceptor) {
				message.getInterceptorChain().remove(
						(XMLFaultOutInterceptor) interceptor);

			}
			// removing for json
			if (interceptor instanceof StaxOutInterceptor.StaxOutEndingInterceptor) {
				message.getInterceptorChain()
						.remove((StaxOutInterceptor.StaxOutEndingInterceptor) interceptor);

			}
		}
		// Btw, I did't abort the chain since I wanted to use a logging
		// interceptor afterwards

	}
}

Reply via email to