1

I'm creating a webservice with cxf in the following way:

<cxf:cxfEndpoint id=XXXEndpoint"
                 serviceClass="com.Sth"
                 address="${webservices.url}/XXX"
                 wsdlURL="${wsdl.address}/services/XXX.wsdl"
                 endpointName="m:XXXPort"
                 serviceName="m:XXXService"
                 xmlns:m="http://com.sth/XXX">
    <cxf:properties>
        <entry key="schema-validation-enabled" value="true" />
    </cxf:properties>
</cxf:cxfEndpoint>

it works perfectly, also added schema validation. I cannot add a custom validation handler. How can I do that?

markus
  • 83
  • 4
  • 9
  • To your statement "I cannot add a customer validaton handler", what have you tried till now ? – Sikorski Oct 04 '13 at 14:11
  • so far I have tried this: like described below. But it doen't work. http://stackoverflow.com/questions/2195034/server-side-xml-validation-with-cxf-webservice I'm runing it on apache service mix 4.5.2 – markus Oct 04 '13 at 17:52
  • Was org.example.MyCustomHandler not called at all? Or the result was unexpected? – Dawid Pytel Oct 04 '13 at 18:15
  • I was able to run custom handler with Apache ServiceMix 4.5.2 using configuration described in my answer. It works as expected. Please note that if you throw an exception from handleEvent method then it is ignored and JAXB behaves as if false was returned and terminates processing. In this case the fault is exactly the same as with default handler. It would help if you could specify what you would like to achieve using the validation handler. – Dawid Pytel Oct 05 '13 at 09:37
  • Hi, the problem is that my handler is never called. But the validation exception is thrown by sax parser - i see it in logs and in soapui – markus Oct 06 '13 at 16:52
  • Could you try to replace your handler with the one I added to my answer? The result should be that you won't get any fault, just validation event will be logged. If it works then it probably means that it's something wrong with your handler. – Dawid Pytel Oct 07 '13 at 13:57

1 Answers1

4

I'm not sure what you mean by custom validation handler.

If you want to change validation error handling you can create class implementing javax.xml.bind.ValidationEventHandler

For instance I used this approach to prevent JAXB from throwing exception on the first encountered error. My custom event handler collected all non-fatal validation errors and thrown appropriate exception after validating whole incoming message.

Sample use of ValidationEventHandler

In order to use your custom validation event handler you should add jaxb-validation-event-handler property:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
        http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">


    <jaxws:endpoint id="HTTPEndpoint"
        implementor="org.dpytel.servicemix.cxf.wsdlfirst.PersonImpl" address="/PersonService"
        wsdlLocation="wsdl/person.wsdl" endpointName="e:soap" serviceName="s:PersonService"
        xmlns:e="http://servicemix.apache.org/samples/wsdl-first" xmlns:s="http://servicemix.apache.org/samples/wsdl-first">
        <jaxws:properties>
            <entry key="schema-validation-enabled" value="true" />
            <entry key="jaxb-validation-event-handler">
                <bean class="org.dpytel.servicemix.cxf.wsdlfirst.MyCustomHandler"></bean>
            </entry>
        </jaxws:properties>
    </jaxws:endpoint>

</beans>

Camel CXF endpoint configuration:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://camel.apache.org/schema/cxf"
    xsi:schemaLocation="
         http://www.springframework.org/schema/beans 
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://camel.apache.org/schema/cxf 
         http://camel.apache.org/schema/cxf/camel-cxf.xsd">

    <cxf:cxfEndpoint id="personEndpoint" address="/person"
        serviceClass="org.apache.servicemix.samples.wsdl_first.Person"
        wsdlURL="wsdl/person.wsdl">
        <cxf:properties>
            <entry key="schema-validation-enabled" value="true" />
            <entry key="jaxb-validation-event-handler">
                <bean class="org.dpytel.servicemix.camel.MyCustomHandler" />
            </entry>
        </cxf:properties>
    </cxf:cxfEndpoint>

</beans>

Example handler that disables validation error and just logs the validation message:

import java.util.logging.Logger;
import javax.xml.bind.ValidationEvent;
import javax.xml.bind.ValidationEventHandler;

public class MyCustomHandler implements ValidationEventHandler {

    private Logger logger = Logger.getLogger(this.getClass().getCanonicalName());

    public boolean handleEvent(ValidationEvent event) {
        logger.severe("Error: " + event.getMessage());
        return true;
    }

}

Please note that some validation errors will cause CXF to skip calling your handler (See details of DataReaderImpl.WSUIDValidationHandler.handleEvent(...)). Your handler will be skipped if error message contains ":Id" string, or is one of the following errors:

  • cvc-type.3.1.1
  • cvc-type.3.2.2
  • cvc-complex-type.3.1.1
  • cvc-complex-type.3.2.2

(frankly it seems like a dirty hack in CXF and if it is a problem for you I would create a bug for CXF team).

If you want more error handling customization you should probably consider writing your own Interceptor. Probably the best phase to perform such validation would be one of (PRE/USER/POST)_LOGICAL.

Dawid Pytel
  • 2,750
  • 1
  • 23
  • 30
  • HI, unfortunatelly it does not work at all. THe handler class is bever called. Any idea? – markus Oct 07 '13 at 15:13
  • I just noticed that you use Camel constructs (cxf:cxfEndpoint) - you never mentioned that. Do you really need Camel endpoint? If not please try replacing it with pure-CXF endpoint definition that I put in my answer. – Dawid Pytel Oct 08 '13 at 06:42
  • I has to be camel endpoint. I guess it won't work in such configuration – markus Oct 08 '13 at 09:17
  • What kind of error you get from SAX parser? I noticed that some errors might result in CXF skipping your handler. I added those to my answer. – Dawid Pytel Oct 08 '13 at 18:39
  • Again, I was able to run custom handler on Apache ServiceMix 4.5.2 with Camel CXF Endpoint. Works like a charm. Are you sure you get unmarshalling error (i.e. related to request message) and not marshalling error (i.e. related to response)? Would it be possible to paste the log entry to the question? – Dawid Pytel Oct 08 '13 at 19:07
  • HI, will you please paste your pom.xml to makse sure we use the same versions? – markus Oct 09 '13 at 15:04
  • 2013-10-09 17:01:07,567 | WARN | wnik/v2/Magazyny | PhaseInterceptorChain | 132 - org.apache.cxf.cxf-api - 2.6.8 | Interceptor for {http://www /uslugi/slownik/v2/Magazyny}MagazynyService#{http://www/uslugi/slownik/v2/Magazyny}stworzMagazyny has thrown exception, unwinding now org.apache.cxf.interceptor.Fault: Could not parse the XML stream caused by: org.xml.sax.SAXParseException: cvc-maxLength-valid: Value '1555555555555555555555555 55555555555555555555' with length = '45' is not facet-valid with respect to maxLength '11' for type 'char11'.. – markus Oct 09 '13 at 15:10
  • Caused by: org.xml.sax.SAXParseException: cvc-maxLength-valid: Value '155555555555555555555555555555555555555555555' with length = '45' is not facet-valid with respect to maxLength '11' for type 'char11'. – markus Oct 09 '13 at 15:11
  • [Project that I used to test](https://github.com/destin/SO-answers/tree/master/camel-cxf-contract-first). Library versions in pom.xml do not matter as ServiceMix provides it's own versions. So assuming we have the same ServiceMix everything should be fine. I used SMX 4.5.2 from SMX download site. – Dawid Pytel Oct 09 '13 at 16:37
  • damn it, i might have not added some magic somehwere :), i do not get any error when beans get loaded (on purpose i set wrong class to see if it even tries to use my class(handler class)) – markus Oct 09 '13 at 16:48
  • Maybe You could send sample project via email? modis2010@o2.pl – markus Oct 09 '13 at 18:34