You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Marian Muller <ma...@serli.com> on 2010/08/23 14:52:40 UTC

Interceptors: sending a custom response before invoking the service ?

Hello all,

I need some help with server-side inbound interceptors.

I am working on a custom interceptor, which performs authentication before
invoking the actual service. My problem is: this interceptor must be able to
directly send a custom response, generated as a javax.xml.soap.SOAPMessage
object, without invoking the service. I already tried some "solutions" based
on what I found in an
old<http://old.nabble.com/Re:-In-OUT-interceptor-of-a-CXF-provider,-how-can-we-stop-the-provider-invoking-its-endpoint-and-send-a-response-back--p25685633.html>
 p<http://old.nabble.com/Re:-In-OUT-interceptor-of-a-CXF-provider,-how-can-we-stop-the-provider-invoking-its-endpoint-and-send-a-response-back--p25685633.html>
ost<http://old.nabble.com/Re:-In-OUT-interceptor-of-a-CXF-provider,-how-can-we-stop-the-provider-invoking-its-endpoint-and-send-a-response-back--p25685633.html>,
but I cannot achieve to send my message correctly. Here is what I tried:

// 1- Get the generated response as a javax.xml.soap.SOAPMessage object
SOAPMessage response = // Get the generated response to send

// 2- Create a CXF-specific response (SoapMessage)
// I tried this solution:
MessageImpl msg = new MessageImpl();
SoapMessage outMessage = new SoapMessage(msg);
// And this other solution:
Exchange exchange = this.currentMessage.getExchange();    //
this.currentMessage is actually the CXF-specific request being processed
(SoapMessage object)
Endpoint ep = exchange.get(Endpoint.class);
Message outMessage = exchange.getOutMessage();
if (outMessage == null) {
    outMessage = ep.getBinding().createMessage();
}

// 3- Set the SOAPMessage response into a CXF-specific response
outMessage.setContent(SOAPMessage.class, response);

// 4- Put the CXF-specific message into the current message exchange
exchange.setOutMessage(soapResponseMsg);
soapResponseMsg.setExchange(exchange);

// 5- Not being able to send the response through the conduit (which, if I
understand, only exists on the client-side), I tried to remove the service
invocation from the interceptor chain:
InterceptorChain inchain = this.currentMessage.getInterceptorChain();
ListIterator<Interceptor<? extends Message>> it = inchain.getIterator();
while (it.hasNext()) {
    Interceptor<? extends Message> icept = it.next();
    if (icept instanceof ServiceInvokerInterceptor) {
        inchain.remove((ServiceInvokerInterceptor)icept);
        break;
    }
}

// I also tried to indicate that the exchange is over, but it just stopped
the processing (this seems to be the solution when working on a server-side
*out*bound interceptor)
exchange.put("exchange.finished", Boolean.TRUE);


I tried many variations, but I keep getting exceptions (mainly caused by
NPEs) when I try to access a webservice. This seems to come from my message
content type (javax.xml.soap.SOAPMessage) or most probably from the way I am
trying to set it inside the response (CXF SoapMessage). The exceptions I get
when using the code(s) above are of this kind in the outbound chain (
org.ow2.jonas.example.jaspic.ws contains the service I am actually
requesting):

2010-08-23 14:46:43,231 : LogUtils.log : Interceptor for {
http://ws.jaspic.example.jonas.ow2.org/}NewWebServiceService#{http://ws.jaspic.example.jonas.ow2.org/}testOperationhas
thrown exception, unwinding now
org.apache.cxf.interceptor.Fault
at
org.apache.cxf.jaxws.interceptors.WrapperClassOutInterceptor.handleMessage(WrapperClassOutInterceptor.java:119)
 at
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:243)
 at
org.apache.cxf.interceptor.OutgoingChainInterceptor.handleMessage(OutgoingChainInterceptor.java:78)
 at
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:243)
 at
org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:110)
 at
org.ow2.jonas.ws.cxf.http.JOnASDestination.invoke(JOnASDestination.java:111)
 at org.ow2.jonas.ws.cxf.jaxws.CXFWSEndpoint.invoke(CXFWSEndpoint.java:151)
 at
org.ow2.jonas.ws.jaxws.http.servlet.JAXWSServlet.invokeDestination(JAXWSServlet.java:113)
 at
org.ow2.jonas.ws.jaxws.http.servlet.JAXWSServlet.doPost(JAXWSServlet.java:75)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
 at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
 at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
 at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
 at
org.ow2.jonas.web.tomcat6.CheckOpenResourcesValve.invoke(CheckOpenResourcesValve.java:73)
 at
org.ow2.jonas.web.tomcat6.tx.TransactionValve.invoke(TransactionValve.java:90)
 at
org.ow2.jonas.web.tomcat6.ResetAuthenticationValve.invoke(ResetAuthenticationValve.java:95)
 at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
 at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
 at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
 at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341)
 at
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
 at
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
 at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
 at java.lang.Thread.run(Thread.java:595)
Caused by: java.lang.NullPointerException
at
org.ow2.jonas.example.jaspic.ws.jaxws_asm.TestOperationResponse_WrapperTypeHelper1.createWrapperObject(Unknown
Source)
 at
org.apache.cxf.jaxws.interceptors.WrapperClassOutInterceptor.handleMessage(WrapperClassOutInterceptor.java:103)
 ... 25 more
2010-08-23 14:46:43,234 : PhaseInterceptorChain.unwind : Invoking
handleFault on interceptor
org.apache.cxf.jaxws.interceptors.WrapperClassOutInterceptor@4db282
[Other fault handling invocations...]


Actually, I think that most of the interceptors in the chains (in- and
out-bound) just cannot handle a SOAPMessage, but only Lists or XML content.
So my questions are: is it possible to create a CXF response message from a
SOAPMessage object ? If so, what would be the best way to do it ? How can I
tell CXF runtime to directly send the response message ?


Thank you very much.
--
Marian MULLER
SERLI

Re: Interceptors: sending a custom response before invoking the service ?

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi

On Mon, Aug 23, 2010 at 3:46 PM, Marian Muller <ma...@serli.com>wrote:

>
>
> Glen Mazza wrote:
> >
> > Hopefully someone else can answer for an interceptor, but I know how to
> do
> > this with a JAX-WS handler at least:
> > http://www.jroller.com/gmazza/entry/jaxws_handler_tutorial , which links
> > to this sample (client-side, but probably similar process for
> > service-side):
> >
> http://svn.apache.org/viewvc/cxf/trunk/distribution/src/main/release/samples/jaxws_handlers/src/demo/handlers/common/SmallNumberHandler.java?view=markup
> >
>
> Thank you. I will take a look at it, but I am not sure that the use of
> JAX-WS handlers is suited to my context. So I am still listening for an
> interceptor-based solution.
>


The JAXRS modules uses few different approaches :

- create a response object in the in interceptor and store it on the
exchange and register a custom invoker which blocks the invocation if the
response object is already available - also register a custom out
interceptor which serializes the response to the output stream first and
then aborts the chain...
- write directly to the HttpServletResponse from the in interceptor (I think
it is available on th in message as AbstractHttpDestination.HTTP_RESPONSE),
add an AbstractHTTPDestination.RESPONSE_COMMITTED to the exchange and have a
custom invoker blocking the invocation if this property exists and also
abort the out chain if needed
- similarly to the above : redirect using RequestDispatcher to some custom
resource, but register an  AbstractHTTPDestination.RESPONSE_REDIRECTED
property instead

cheers, Sergey


> --
> View this message in context:
> http://cxf.547215.n5.nabble.com/Interceptors-sending-a-custom-response-before-invoking-the-service-tp2644637p2644811.html
> Sent from the cxf-user mailing list archive at Nabble.com.
>

Re: Interceptors: sending a custom response before invoking the service ?

Posted by Marian Muller <ma...@serli.com>.

Glen Mazza wrote:
> 
> Hopefully someone else can answer for an interceptor, but I know how to do
> this with a JAX-WS handler at least:
> http://www.jroller.com/gmazza/entry/jaxws_handler_tutorial , which links
> to this sample (client-side, but probably similar process for
> service-side):
> http://svn.apache.org/viewvc/cxf/trunk/distribution/src/main/release/samples/jaxws_handlers/src/demo/handlers/common/SmallNumberHandler.java?view=markup
> 

Thank you. I will take a look at it, but I am not sure that the use of
JAX-WS handlers is suited to my context. So I am still listening for an
interceptor-based solution.
-- 
View this message in context: http://cxf.547215.n5.nabble.com/Interceptors-sending-a-custom-response-before-invoking-the-service-tp2644637p2644811.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Interceptors: sending a custom response before invoking the service ?

Posted by Glen Mazza <gl...@gmail.com>.
[quote]I am working on a custom interceptor, which performs authentication
before
invoking the actual service. My problem is: this interceptor must be able to
directly send a custom response, generated as a javax.xml.soap.SOAPMessage
object, without invoking the service.[/quote]

Hopefully someone else can answer for an interceptor, but I know how to do
this with a JAX-WS handler at least:
http://www.jroller.com/gmazza/entry/jaxws_handler_tutorial , which links to
this sample (client-side, but probably similar process for service-side):
http://svn.apache.org/viewvc/cxf/trunk/distribution/src/main/release/samples/jaxws_handlers/src/demo/handlers/common/SmallNumberHandler.java?view=markup




-- 
View this message in context: http://cxf.547215.n5.nabble.com/Interceptors-sending-a-custom-response-before-invoking-the-service-tp2644637p2644746.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Interceptors: sending a custom response before invoking the service ?

Posted by jbright <jo...@gmail.com>.
Hi Dan,

Where do we get the 'context' here?

SOAPMessage soapMessage = ((SOAPMessageContext)context).getMessage(); 

Kindly reply



--
View this message in context: http://cxf.547215.n5.nabble.com/Interceptors-sending-a-custom-response-before-invoking-the-service-tp2644637p5719401.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Interceptors: sending a custom response before invoking the service ?

Posted by sachin123 <sa...@gmail.com>.
In your below code, from where you get the context back ??I am trying to the
same when you are doing.Basically aborting the interceptor chain and sending
the SOAP Message response back without hitting Service EndPoint.

SOAPMessage soapMessage =
((SOAPMessageContext)context).getMessage(); 

Please let me know

Thanks
Sachin



--
View this message in context: http://cxf.547215.n5.nabble.com/Interceptors-sending-a-custom-response-before-invoking-the-service-tp2644637p5711718.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Interceptors: sending a custom response before invoking the service ?

Posted by sea_chen <se...@hotmail.com>.
Hi Gagan,
I am trying wo find similar solution, too. Have you worked out?
-- 
View this message in context: http://cxf.547215.n5.nabble.com/Interceptors-sending-a-custom-response-before-invoking-the-service-tp2644637p3380708.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Interceptors: sending a custom response before invoking the service ?

Posted by Gagan <ga...@gmail.com>.
hi Marian,

I am trying to find similar solution. Can you share your solution to this
problem?
-- 
View this message in context: http://cxf.547215.n5.nabble.com/Interceptors-sending-a-custom-response-before-invoking-the-service-tp2644637p3368688.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Interceptors: sending a custom response before invoking the service ?

Posted by Marian Muller <ma...@serli.com>.

Daniel  Kulp wrote:
> 
> Here is the code that the JAX-WS SoapHandler things use for this.   This
> may 
> help.  It MAY require the SAAJOutInterceptor configured in as well.  Not 
> really sure.
> 
> Dan
> 
> 
> // server side inbound
>                 message.getInterceptorChain().abort();
>                 Endpoint e = message.getExchange().get(Endpoint.class);
>                 if (!message.getExchange().isOneWay()) {
>                     Message responseMsg = new MessageImpl();
>                     responseMsg.setExchange(message.getExchange());
>                     responseMsg =
> e.getBinding().createMessage(responseMsg);
>                     message.getExchange().setOutMessage(responseMsg);
>                     SOAPMessage soapMessage = 
> ((SOAPMessageContext)context).getMessage();
> 
>                     responseMsg.setContent(SOAPMessage.class,
> soapMessage);
> 
>                     InterceptorChain chain = 
> OutgoingChainInterceptor.getOutInterceptorChain(message
>                         .getExchange());
>                     responseMsg.setInterceptorChain(chain);
>                     // so the idea of starting interceptor chain from any
>                     // specified point does not work
>                     // well for outbound case, as many outbound
> interceptors
>                     // have their ending interceptors.
>                     // For example, we can not skip
> MessageSenderInterceptor.
>                     chain.doInterceptStartingAfter(responseMsg, 
>                                                   
> SoapPreProtocolOutInterceptor.class.getName());
>                 }
> 

Thank you very much !! It worked out of the box !

My issue is solved :-) And your code is far more clean than what I was
trying to do ;-)

Thanks again (and for all the other interesting posts too).
-- 
View this message in context: http://cxf.547215.n5.nabble.com/Interceptors-sending-a-custom-response-before-invoking-the-service-tp2644637p2650870.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Interceptors: sending a custom response before invoking the service ?

Posted by Daniel Kulp <dk...@apache.org>.

Here is the code that the JAX-WS SoapHandler things use for this.   This may 
help.  It MAY require the SAAJOutInterceptor configured in as well.  Not 
really sure.

Dan


// server side inbound
                message.getInterceptorChain().abort();
                Endpoint e = message.getExchange().get(Endpoint.class);
                if (!message.getExchange().isOneWay()) {
                    Message responseMsg = new MessageImpl();
                    responseMsg.setExchange(message.getExchange());
                    responseMsg = e.getBinding().createMessage(responseMsg);
                    message.getExchange().setOutMessage(responseMsg);
                    SOAPMessage soapMessage = 
((SOAPMessageContext)context).getMessage();

                    responseMsg.setContent(SOAPMessage.class, soapMessage);

                    InterceptorChain chain = 
OutgoingChainInterceptor.getOutInterceptorChain(message
                        .getExchange());
                    responseMsg.setInterceptorChain(chain);
                    // so the idea of starting interceptor chain from any
                    // specified point does not work
                    // well for outbound case, as many outbound interceptors
                    // have their ending interceptors.
                    // For example, we can not skip MessageSenderInterceptor.
                    chain.doInterceptStartingAfter(responseMsg, 
                                                   SoapPreProtocolOutInterceptor.class.getName());
                }




On Monday 23 August 2010 8:52:40 am Marian Muller wrote:
> Hello all,
> 
> I need some help with server-side inbound interceptors.
> 
> I am working on a custom interceptor, which performs authentication before
> invoking the actual service. My problem is: this interceptor must be able
> to directly send a custom response, generated as a
> javax.xml.soap.SOAPMessage object, without invoking the service. I already
> tried some "solutions" based on what I found in an
> old<http://old.nabble.com/Re:-In-OUT-interceptor-of-a-CXF-provider,-how-can
> -we-stop-the-provider-invoking-its-endpoint-and-send-a-response-back--p2568
> 5633.html>
> p<http://old.nabble.com/Re:-In-OUT-interceptor-of-a-CXF-provider,-how-can-
> we-stop-the-provider-invoking-its-endpoint-and-send-a-response-back--p25685
> 633.html>
> ost<http://old.nabble.com/Re:-In-OUT-interceptor-of-a-CXF-provider,-how-ca
> n-we-stop-the-provider-invoking-its-endpoint-and-send-a-response-back--p256
> 85633.html>, but I cannot achieve to send my message correctly. Here is
> what I tried:
> 
> // 1- Get the generated response as a javax.xml.soap.SOAPMessage object
> SOAPMessage response = // Get the generated response to send
> 
> // 2- Create a CXF-specific response (SoapMessage)
> // I tried this solution:
> MessageImpl msg = new MessageImpl();
> SoapMessage outMessage = new SoapMessage(msg);
> // And this other solution:
> Exchange exchange = this.currentMessage.getExchange();    //
> this.currentMessage is actually the CXF-specific request being processed
> (SoapMessage object)
> Endpoint ep = exchange.get(Endpoint.class);
> Message outMessage = exchange.getOutMessage();
> if (outMessage == null) {
>     outMessage = ep.getBinding().createMessage();
> }
> 
> // 3- Set the SOAPMessage response into a CXF-specific response
> outMessage.setContent(SOAPMessage.class, response);
> 
> // 4- Put the CXF-specific message into the current message exchange
> exchange.setOutMessage(soapResponseMsg);
> soapResponseMsg.setExchange(exchange);
> 
> // 5- Not being able to send the response through the conduit (which, if I
> understand, only exists on the client-side), I tried to remove the service
> invocation from the interceptor chain:
> InterceptorChain inchain = this.currentMessage.getInterceptorChain();
> ListIterator<Interceptor<? extends Message>> it = inchain.getIterator();
> while (it.hasNext()) {
>     Interceptor<? extends Message> icept = it.next();
>     if (icept instanceof ServiceInvokerInterceptor) {
>         inchain.remove((ServiceInvokerInterceptor)icept);
>         break;
>     }
> }
> 
> // I also tried to indicate that the exchange is over, but it just stopped
> the processing (this seems to be the solution when working on a server-side
> *out*bound interceptor)
> exchange.put("exchange.finished", Boolean.TRUE);
> 
> 
> I tried many variations, but I keep getting exceptions (mainly caused by
> NPEs) when I try to access a webservice. This seems to come from my message
> content type (javax.xml.soap.SOAPMessage) or most probably from the way I
> am trying to set it inside the response (CXF SoapMessage). The exceptions
> I get when using the code(s) above are of this kind in the outbound chain
> ( org.ow2.jonas.example.jaspic.ws contains the service I am actually
> requesting):
> 
> 2010-08-23 14:46:43,231 : LogUtils.log : Interceptor for {
> http://ws.jaspic.example.jonas.ow2.org/}NewWebServiceService#{http://ws.jas
> pic.example.jonas.ow2.org/}testOperationhas thrown exception, unwinding now
> org.apache.cxf.interceptor.Fault
> at
> org.apache.cxf.jaxws.interceptors.WrapperClassOutInterceptor.handleMessage(
> WrapperClassOutInterceptor.java:119) at
> org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChai
> n.java:243) at
> org.apache.cxf.interceptor.OutgoingChainInterceptor.handleMessage(OutgoingC
> hainInterceptor.java:78) at
> org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChai
> n.java:243) at
> org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationO
> bserver.java:110) at
> org.ow2.jonas.ws.cxf.http.JOnASDestination.invoke(JOnASDestination.java:111
> ) at
> org.ow2.jonas.ws.cxf.jaxws.CXFWSEndpoint.invoke(CXFWSEndpoint.java:151) at
> org.ow2.jonas.ws.jaxws.http.servlet.JAXWSServlet.invokeDestination(JAXWSSer
> vlet.java:113) at
> org.ow2.jonas.ws.jaxws.http.servlet.JAXWSServlet.doPost(JAXWSServlet.java:7
> 5) at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
>  at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
>  at
> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Applicatio
> nFilterChain.java:290) at
> org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterC
> hain.java:206) at
> org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.j
> ava:233) at
> org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.j
> ava:191) at
> org.ow2.jonas.web.tomcat6.CheckOpenResourcesValve.invoke(CheckOpenResources
> Valve.java:73) at
> org.ow2.jonas.web.tomcat6.tx.TransactionValve.invoke(TransactionValve.java:
> 90) at
> org.ow2.jonas.web.tomcat6.ResetAuthenticationValve.invoke(ResetAuthenticati
> onValve.java:95) at
> org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:12
> 7) at
> org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:10
> 2) at
> org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.jav
> a:109) at
> org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341)
>  at
> org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
>  at
> org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Htt
> p11Protocol.java:588) at
> org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) at
> java.lang.Thread.run(Thread.java:595)
> Caused by: java.lang.NullPointerException
> at
> org.ow2.jonas.example.jaspic.ws.jaxws_asm.TestOperationResponse_WrapperType
> Helper1.createWrapperObject(Unknown Source)
>  at
> org.apache.cxf.jaxws.interceptors.WrapperClassOutInterceptor.handleMessage(
> WrapperClassOutInterceptor.java:103) ... 25 more
> 2010-08-23 14:46:43,234 : PhaseInterceptorChain.unwind : Invoking
> handleFault on interceptor
> org.apache.cxf.jaxws.interceptors.WrapperClassOutInterceptor@4db282
> [Other fault handling invocations...]
> 
> 
> Actually, I think that most of the interceptors in the chains (in- and
> out-bound) just cannot handle a SOAPMessage, but only Lists or XML content.
> So my questions are: is it possible to create a CXF response message from a
> SOAPMessage object ? If so, what would be the best way to do it ? How can I
> tell CXF runtime to directly send the response message ?
> 
> 
> Thank you very much.
> --
> Marian MULLER
> SERLI

-- 
Daniel Kulp
dkulp@apache.org
http://dankulp.com/blog