On Thu October 22 2009 4:31:21 pm Brenda Coulson wrote:
> That is great to know! I am so confused between the difference between
> Interceptors and Handlers and when to use them. Ok so I have a Soap message
> that I am trying to ultimately validate. However, there are times when I
>  may receive a message that does not specify the namespace for the soap
>  payload. Example as follows:
> 
> <soapenv:Envelope
>  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/";>
>  <soapenv:Header/>
>    <soapenv:Body>
>       <getReference>
>          <agcHcsId>80640</agcHcsId>
>       </getReference>
>    </soapenv:Body>
> </soapenv:Envelope>

Oi..  Ick..  Technically, that's an invalid soap message as, according to 
spec, direct child elements of soap:Body must be namespace qualified.   But 
let's ignore that issue for a second.   :-)

> Technically the XML inside the payload is well-formed so the validator does
> not complain. However, there is a required element, referenceId, missing.
>  So as I am validating, I would like to just get to the Soap payload, aka
> 
>       <getReference>
>          <agcHcsId>80640</agcHcsId>
>       </getReference>
> 
> And validate it against my schema, regardless of whether or no the
>  namespace is specified. I need to do this for all methods on my web
>  service, one of which has a Soap attachment, which based on other posts I
>  saw, may cause some problems with the different processing phases.
> 
> Net effect is how do I just get the Soap payload part of the message? If I
> don't need to use a Logical Handler, great. If I do, great too. Does not
> matter to me.

OK.  There are a couple of options that you could pursue for this.

1) You COULD write an interceptor that lives just before the 
DocLiteralInInterceptor that takes the XMLStreamReader and wrappers it with a 
new XMLStreamReader that would "correct" the namespace issue.   (override the 
getNamespace calls and such to return the correct value).   If you do that, 
you could just turn on the CXF built in schema validation stuff.    See:
http://cxf.apache.org/faq.html
That option would have the best performance as the built in jaxb validation 
doesn't need to load the whole message while unmarshalling.   

2) Next easiest is to configure in the SAAJInInterceptor (or have your 
interceptor call it) and work with the SAAJ model directly.   Your interceptor 
would just look something like:


    public MyInterceptor() {
        super(Phase.PRE_PROTOCOL);
        getAfter().add(SAAJInInterceptor.class.getName());
    }
    public void handleMessage(SoapMessage msg) throws Fault {
        SOAPMessage doc = msg.getContent(SOAPMessage.class);
        if (doc == null) {
            saajIn.handleMessage(msg);
            doc = msg.getContent(SOAPMessage.class);
        }
       //process doc here
    }

Not quite as good as it loads the whole message into memory, but certainly 
easy to work with.

3) Register a jaxws LogicalHandler with the endpoint.   The 
LogicalMessageContext that is passed in has a getLogicalMessage().getPayload() 
method that returns a Source.    (I think a DOMSource is what we return)    
Advantage here is that it would be portable to other jaxws implementations.   
Disadvantage is that performance is way worse than option 2.   Also, JAX-WS 
handlers have to be registered per-endpoint whereas an interceptor can be 
configured on the Bus and thus be more "global".

Hope that helps!

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

Reply via email to