Apache CFX Schema validation - contract first - web-services

I am developing a Web service using Apache CXF and contract first approach with schema validation. Problem is, that validation is not working. There is no error, so it like is not activated. But validation is configured.
So, I have took a look to official Apache CXF examples you can find here.
I took a look to wsdl_first example and modify it adding schema validation and some restriction in WSDL:
<!-- HTTP Endpoint -->
<jaxws:endpoint xmlns:customer="http://customerservice.example.com/"
id="CustomerServiceHTTP" address="http://localhost:9090/CustomerServicePort"
serviceName="customer:CustomerServiceService" endpointName="customer:CustomerServiceEndpoint"
implementor="com.example.customerservice.server.CustomerServiceImpl">
<jaxws:features>
<bean class="org.apache.cxf.feature.LoggingFeature" />
</jaxws:features>
<!-- schema validation-->
<jaxws:properties>
<entry key="schema-validation-enabled" value="true" />
</jaxws:properties>
</jaxws:endpoint>
To my surprise, it doesn't work either.
OK, so I took a look to wsdl_first_xmlbeans example, where according with the README.txt file, it also shows how CXF configuration can be used to enable schema validation.
And for this example, schema validation works. The difference between both examples is that the second one use JAX-WS APIs and with the XMLBeans approach. Does it have something to do? Why schema validation is not working for first example? Probably, I am missing something.

For validation on the service side, it would likely need to have a wsdlLocation attribute set on the jaxws:endpoint so it would load the WSDL (that would then contain the schemas). Currently, the validation in that example is on the client side only. If you run the service, the log shows:
INFO: Creating Service {http://server.customerservice.example.com/}CustomerServiceImplService from class com.example.customerservice.CustomerService
which shows it's not using the WSDL at all.

Related

Can`t enable WS-SecurityPolice with CXF in Web Service

It`s my first project with CXF and Web Services,using Tomcat as a servlet container and my first question in StackOverflow too,so be patient with me....;-)
I'm using :
Tomcat 9 (standalone and integrated with Eclipse).
CXF (3.2.0)
JDK 1.8
Windows 7
**The problem:**WS-SecurityPolicy not enabled/ not working in the server side.
WS-SecurityPolicy is implemented in the wsdl file of the web service and the policy seems working fine,because in the client side the SOAP output message body is signed.
The problem I'm stuck is in the server side,none of the policies are applied in response.
The first issue I had was with the SOAP header "must understand=1",the server does not recognize the security headers and throws an exception.
My suspect was that the web service is not applying the policy,then to avoid the exception of the header I put a handler that does nothing whith it.
Now the server response the SOAP message but in clear form (unsigned, without the BinarySecurityTolen and other stuff),my suspect was true,the policy is not working.
I think the porblem is a misconfiguration of CXF files...
The cxf bean configuration of the web service is loaded during Tomcat's startup.
INFO: Creating Service {http://ole/wsTransaccion}WsTransaccionService from WSDL: wsdl/wsTransaccion.wsdl
....
....
INFO: Loading XML bean definitions from ServletContext resource [/WEB-INF/cxf-wsTransaccion.xml]
The cxf-wsTransaccion.xml file contains:
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<bean id="myPasswordCallback"
class="implementacion.ServerKeystorePasswordCallback" />
<jaxws:endpoint xmlns:tns="http://ole/wsTransaccion" id="wsTransaccion"
implementor="implementacion.WsTransaccionImpl"
wsdlLocation="wsdl/wsTransaccion,wsdl" endpointName="tns:WsTransaccionPort"
serviceName="tns:WsTransaccionService" address="/WsTransaccionPort">
<jaxws:features>
<bean class="org.apache.cxf.feature.LoggingFeature" />
</jaxws:features>
<jaxws:properties>
<entry key="security.callback-handler">
<ref bean="myPasswordCallback"/>
</entry>
<entry key="security.encryption.properties" value="keystore.properties"/>
<entry key="security.signature.properties" value="keystore.properties"/>
<entry key="ws-security.encryption.username" value="useReqSigCert"/>
</jaxws:properties>
</jaxws:endpoint>
I think the problem coluld be in the location of the file keystore.properties, although no exception is thrown (like a java.io.FileNotFoundException) if not exists..
All examples I saw were Maven's projects ,but this is NOT A MAVEN project so I haven't the folder "resources" where properties files and keystore are placed.
I don't know the right place of keystore.properties, i think must be in the classpath ,then i put it in a package named resources with the keystore together.
The content of keystore.properties:
>org.apache.wss4j.crypto.provider=org.apache.ws.security.components.crypto.Merlin
>org.apache.wss4j.crypto.merlin.keystore.file=server.p12
>org.apache.wss4j.crypto.merlin.keystore.type=PKCS12
>org.apache.wss4j.crypto.merlin.keystore.alias=server
>org.apache.wss4j.crypto.merlin.keystore.password=xxxxxx<br/>
Other possibility is that org.apache.wss4j.crypto.merlin.keystore.file=server.p12 is not in the right place too, although is in the same place like keystore.properties
Any suggestion would be very appreciated.
Thanks very much!!!.
The problem was here:
Tomcat console:
"WARNING: Resource classpath:./resources/policyBinding.xml was not found in the classloaders."Although policyBinding.xml is in the classpath is not properly loaded due to the following annotation in the interface of the web service:
#Policy(uri = "./resources policyBinding.xml",placement=Policy.Placement.DEFAULT)
Thank you to Alfredo (WS-Security Policy node not being generated in Apache CXF with Spring and custom context file
) i figured it out the right syntax:
#Policy(uri = "classpath:policyBinding.xml",placement=Policy.Placement.DEFAULT)

Apache ServiceMix! Request-Replay Web Service message

Hello!
I'm trying to learn some Apache Camel and Apache CXF and of course I've ran into some problems.
What I'm trying to do:
Send timed SOAP messages from ESB to some web service, wait for the reponse from the web service and process it. I'm using Apache ServiceMix!.
What I've done:
Implemented a WSDL file with two operations PingOutput (what I'm sending) and PingInput (what I want to receive from the WS).
Implemented a CXF Endpoint (http://127.0.0.1:8090/ping_ws is a WS mocked with SoapUI):
<cxf:cxfEndpoint address="http://127.0.0.1:8090/ping_ws"
id="Ping_Mocked_WS" wsdlURL="ping.wsdl">
<cxf:properties>
<entry key="dataFormat" value="PAYLOAD" />
</cxf:properties>
</cxf:cxfEndpoint>
Implemented a Camel route:
<camelContext xmlns="http://camel.apache.org/schema/spring" streamCache="true">
<route id="ping-ws">
<from uri="timer://ping_timer?fixedRate=true&period=10000"/>
<bean ref="PingBean" method="createPingRequest" />
<to uri="cxf:bean:Ping_Mocked_WS"/>
<bean ref="PingBean" method="processPingResponse" />
</route>
</camelContext>
What I do not understand:
Why the <bean ref="PingBean" method="processPingResponse" /> gets the correct response from SoapUI (the PingOutput operation defined in WSDL)?
Is this the correct way to achieve my goal? And by this way I mean with one single route?
The codes work correctly, I might have some typos here, please do not mind them.
Thanks!
Ad 1)
Likely because the type defined in the method signature of the processPingResponse method. Camel uses bean parameter binding, and based on the type, it uses its type converter to convert to the given type.
And as the payload is a SOAP response in XML it can use JAXB to convert from XML to the type from the method signature.
To do so it uses camel-jaxb which ServiceMix comes with out of the box.
Ad2)
The route works. What it is you want to do differently?

cxf webservice over jms, how to get wsdl

I have a webservice configured like this.
<jaxws:endpoint
id="helloWorld"
xmlns:hello="http://service.test.com/"
serviceName="hello:MyServiceImplService"
endpointName="hello:MyServiceImplPort" address="jms://"
implementor="com.test.service.MyServiceImpl" >
<jaxws:features>
<bean class="org.apache.cxf.feature.LoggingFeature" />
<bean class="org.apache.cxf.transport.jms.JMSConfigFeature">
<property name="jmsConfig" ref="jmsConfig"/>
</bean>
</jaxws:features>
</jaxws:endpoint>`
I want to have the cxf generate the wsdl for me. when the service is http, I can access the wsdl from a url like this http://localhost:8080/server/hello?wsdl, after I change the transport to jms, how do I access the wsdl? what's the jms message I need to send to get the wsdl. or I have to write the wsdl first and expose it through a regular http request. I am asking this because the client need to know the wsdl to get all the type and binding information to generate class. client should already know how to connect the queue.
You can use commandline java2ws tool (see http://cxf.apache.org/docs/java-to-ws.html) passing it your implementation class. There is also a sample invocation from Ant script. It will generate WSDL which your client can use to generate client code.

Spring web services validation

I've two kinds of webservices:
webservices that need the request to be validated
others that must not be validated by Spring.
Is this possible in Spring?
I know about ValidatingInterceptor, but can we have two of these?
The reason for not validating one type of web service is that the request is not defined: what's sent in the request, depends on many things.
I am using Spring 3.0, with schema XSD's for my webservices.
Any suggestions?
Adi
You can use two payloadroot within a interceptor for that purpose.
All you need to do is to set validateRequest/validateResponse as true or false as required.
Here is a sample:
<sws:interceptors>
<sws:payloadRoot namespaceUri="uri1">
<bean id="validator1forUri1"
class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor"
p:schema="classpath:/WEB-INF/xsds/tovalidate.xsd" p:validateRequest="true"
p:validateResponse="true" />
</sws:payloadRoot>
<sws:payloadRoot namespaceUri="uri2">
<bean id="validator2forUri2"
class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor"
p:schema="classpath:/WEB-INF/xsds/nottovalidate.xsd"
p:validateRequest="false" p:validateResponse="false" />
</sws:payloadRoot>
</sws:interceptors>

Securing Web Service communication with SSL using CXF

I am trying to secure communications via SSL/TLS for one of our Web Service using CXF 2.2.5.
I am wondering how to update client and server Spring configuration file to activate this feature.
I found some information on CXF's website (CXF Wiki) for the client configuration, here is the given example:
<http:conduit name="{http://apache.org/hello_world}HelloWorld.http-conduit">
<http:tlsClientParameters>
<sec:keyManagers keyPassword="password">
<sec:keyStore type="JKS" password="password"
file="src/test/java/org/apache/cxf/systest/http/resources/Morpit.jks"/>
</sec:keyManagers>
<sec:trustManagers>
<sec:keyStore type="JKS" password="password"
file="src/test/java/org/apache/cxf/systest/http/resources/Truststore.jks"/>
</sec:trustManagers>
<sec:cipherSuitesFilter>
<!-- these filters ensure that a ciphersuite with
export-suitable or null encryption is used,
but exclude anonymous Diffie-Hellman key change as
this is vulnerable to man-in-the-middle attacks -->
<sec:include>.*_EXPORT_.*</sec:include>
<sec:include>.*_EXPORT1024_.*</sec:include>
<sec:include>.*_WITH_DES_.*</sec:include>
<sec:include>.*_WITH_NULL_.*</sec:include>
<sec:exclude>.*_DH_anon_.*</sec:exclude>
</sec:cipherSuitesFilter>
</http:tlsClientParameters>
<http:authorization>
<sec:UserName>Betty</sec:UserName>
<sec:Password>password</sec:Password>
</http:authorization>
<http:client AutoRedirect="true" Connection="Keep-Alive"/>
</http:conduit>
Concerning this configuration, the
Concerning the server side configuration I am unable to launch the server properly, here is the configuration I have:
<http:destination name="{urn:ihe:iti:xds-b:2007}DocumentRepository_Port_Soap12.http-destination">
</http:destination>
<httpj:engine-factory>
<httpj:engine port="9043">
<httpj:tlsServerParameters>
<sec:keyManagers keyPassword="changeit">
<sec:keyStore type="JKS" password="changeit" file="security/keystore.jks" />
</sec:keyManagers>
<sec:trustManagers>
<sec:keyStore type="JKS" password="changeit" file="security/cacerts.jks" />
</sec:trustManagers>
<sec:cipherSuitesFilter>
<!--
these filters ensure that a ciphersuite with export-suitable or null encryption is used, but exclude
anonymous Diffie-Hellman key change as this is vulnerable to man-in-the-middle attacks
-->
<sec:include>.*_EXPORT_.*</sec:include>
<sec:include>.*_EXPORT1024_.*</sec:include>
<sec:include>.*_WITH_DES_.*</sec:include>
<sec:include>.*_WITH_NULL_.*</sec:include>
<sec:exclude>.*_DH_anon_.*</sec:exclude>
</sec:cipherSuitesFilter>
<sec:clientAuthentication want="true" required="true" />
</httpj:tlsServerParameters>
</httpj:engine>
</httpj:engine-factory>
But when I run my application server (JOnas) with this configuration I have the following error message:
Line 20 in XML document from ServletContext resource [/WEB-INF/beans.xml] is invalid; nested exception is org.xml.sax.SAXParseException: cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'httpj:engine-factory'.
Do you guys know how to solve this issue?
Thanks in advance,
It sounds like you are missing a namespace declaration or you have fat-fingered your XML. This is likely more of a Spring related issue than a CXF issue.
Check that the following items appear on your beans element where you declare httj:engine-factory:
<beans
...
xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration"
...
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://cxf.apache.org/transports/http-jetty/configuration http://cxf.apache.org/schemas/configuration/http-jetty.xsd
...">
<import resource="classpath:META-INF/cxf/cxf-extension-http.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-http-jetty.xml" />
Check that the CXF Jetty Transport JAR is in your classpath at runtime.
If you add the declaration and the schema location to your context file in your IDE (at least in Eclipse with the Spring plug-ins and IDEA) you should get schema validation right in your IDE so you can easily find any mistakes you make and take advantage of auto-completion.