Schema validation in JAX WW web service - web-services

I am developing web services using jax-ws and apache cxf with code first approach . I want to enable schema validation in my service . For this I have configured the cxf configuration file as follows
<jaxws:endpoint id="testService"
implementorClass="com.test.impl.TestServiceImpl"
implementor="#testServiceImpl"
address="/testService">
<jaxws:serviceFactory>
<ref bean="jaxws-and-aegis-service-factory"/>
</jaxws:serviceFactory>
<jaxws:properties>
<entry key="schema-validation-enabled" value="true"/>
</jaxws:properties>
</jaxws:endpoint>
Service,
#WebService
#SOAPBinding(style=SOAPBinding.Style.DOCUMENT,use=SOAPBinding.Use.LITERAL)
public interface TestService {
#WebMethod
String test(MyVo myVo) ;
}
MyVo,
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "MyVo")
public class MyVo {
#XmlElement(name = "name", required = true)
private String name;
............. // getter and setter
}
.
But after deploying the service wsdl looks like
<xsd:complexType name="MyVo">
<xsd:sequence>
<xsd:element minOccurs="0" name="name" nillable="true" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
As per documentation minOccurs should be 1 (because of required=true ) .
Also I am able to call service without setting name attribute in MyVo object . No error is coming from server.
I have created a endorsed directory in my jre\lib folder and jdk\lib folder and put jaxb-api-2.2.jar and jaxws-api-2.2.1.jar there . Still facing same problem . I am using jdk1.6.0_11.
Thanks
Please advice .

Related

Camel cxf pax-web Handle WS-Security Username token

I'm implementing a web service using camel cxf to be deployed in Karaf.
I'm using the pax web that comes with karaf. I'm using the cxf codegen plugin in pom to do wsdl to java.
I'm defining the cxf uri and the routes in the RouteBuilder Java DSL. The blueprint.xml only has some beans and ref to the RouteBuilder.
final String cxfUri =
String.format("cxf:%s?serviceClass=%s&wsdlURL=wsdl/Event.wsdl",
"/Event.jws", com.example.EventPortType.class.getCanonicalName());
I have setup ssl with the pax-web(jetty.xml). If i send the WSSE security headers with username and password, it generates a MustUnderstand soap fault.
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" S:mustUnderstand="1">
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Id-LdZa8aaGdy7mWQWXLp_zpbfg">
<wsse:Username>xxx</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">xxx</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
The input request cannot be changed.
I get this exception.
<soap:Fault>
<faultcode>soap:MustUnderstand</faultcode>
<faultstring>MustUnderstand headers: [{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security] are not understood.</faultstring>
</soap:Fault>
How can i secure the cxf endpoint to authenticate the request?
Thank you.
you need to add a WSS4J interceptors to the exposed CXF service. You can provide your own PasswordCallback for the user validation, but I prefer to leverage the native JAAS. This is a blueprint example requiring the UsernameToken with any Karaf user (this is for exposing a camel-cxf routes, however the same principle applies to the pure CXF implementation). If you prefer Java based Camel route builders, you may add the interceptor beans to the context registry to use them. But - the blueprint (or spring config) allows you to more fine-grained control than simple endpoint parameters.
<?xml version="1.0" encoding="UTF-8"?>
<blueprint
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://cxf.apache.org/blueprint/core"
xmlns:camelcxf="http://camel.apache.org/schema/blueprint/cxf"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xmlns:jaxws="http://cxf.apache.org/blueprint/jaxws"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd http://camel.apache.org/schema/blueprint
http://camel.apache.org/schema/blueprint/camel-blueprint.xsd http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0
http://svn.apache.org/repos/asf/aries/trunk/blueprint/blueprint-cm/src/main/resources/org/apache/aries/blueprint/compendium/cm/blueprint-cm-1.1.0.xsd
http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
http://cxf.apache.org/blueprint/jaxws http://cxf.apache.org/schemas/blueprint/jaxws.xsd
http://camel.apache.org/schema/blueprint/cxf http://camel.apache.org/schema/cxf/camel-cxf-2.7.5.xsd">
<bean id="authenticationInterceptor" class="org.apache.cxf.interceptor.security.JAASLoginInterceptor">
<property name="contextName" value="karaf"/>
<property name="roleClassifier" value="RolePrincipal"/>
<property name="roleClassifierType" value="classname"/>
</bean>
<bean id="wsSecInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<argument>
<map>
<entry key="action" value="UsernameToken"/>
<entry key="passwordType" value="PasswordText"/>
</map>
</argument>
</bean>
<!-- ================ Apache Camel impl ======================= -->
<camelcxf:cxfEndpoint id="testService2"
address="/api/2.0/external/TestService"
xmlns:apogado="http://test.ws.apogado.com/v1_0/ws"
endpointName="apogado:AddressServicePort"
serviceName="apogado:AddressService"
wsdlURL="classpath:/xsd/ws/TestService.wsdl"
>
<camelcxf:properties>
<entry key="dataFormat" value="PAYLOAD" />
<entry key="ws-security.ut.no-callbacks" value="true"/>
<entry key="ws-security.validate.token" value="false"/>
</camelcxf:properties>
<camelcxf:inInterceptors>
<ref component-id="wsSecInterceptor" />
<ref component-id="authenticationInterceptor"/>
</camelcxf:inInterceptors>
<camelcxf:features>
</camelcxf:features>
</camelcxf:cxfEndpoint>
<camelContext xmlns="http://camel.apache.org/schema/blueprint" id="testWsCtx" trace="true">
<!-- your service implementation -->
<route>
<from uri="testService2" />
<to uri="..." />
<route>
</camelContext>
</blueprint>

Authorize.NET GetCustomerProfile not returning data

I have been using Authorize.NET's GetCustomerProfile for many years and suddenly today the response is not returning a payment profile. It just returns an array of profiles, but all important fields (such as payment) are null.
(This is part of their CIM feature where an 'obfuscated' payment profile is returned and should be something like XXXX1234)
I am using a generated proxy within Visual Studio to the URL https://api.authorize.net/soap/v1/Service.asmx?WSDL (which generates a References.cs file)
I had a similar issue on the CreateCustomerPaymentProfile SOAP call (via .NET auto-generated proxy) that just started yesterday, 11/3/2015, even though we've been successfully interfacing the SOAP CIM for a couple years.
I was able to "fix" the issue by doing an "Update Service Reference" in Visual Studio to regenerate the proxy classes based on their latest WSDL. There were several changes in the WSDL.
Specifically, on my end it appeared as if the response was not including a value for the customerPaymentProfileId after being successfully created on their end. In reality, they were in fact still sending this value, but there was a new field above it in the XML response, customerProfileId. As Simon_Weaver mentioned in his answer, the proxy classes generated by Visual Studio have explicit ordering of fields that are required for proper deserialization. The addition of this previously "unknown" field above a known field caused it to break my code.
Luckily this new customerProfileId was included in their latest WSDL so an "Update Service Reference" and recompile fixed my issue.
I informed Authorize.net support of my issue in great detail and told them they need to include any new fields at the end of the "sequence" in the WSDL document in order to not break and clients using older versions of the WSDL. So far I have not heard a response from them, but I would encourage anyone else who experienced this issue, even if you've already worked-around it, to report it to them at support#authorize.net so they don't accidently do this again.
Well hello Simon!
It looks like Authorize.NET updated their service with new fields but forgot to add them to the WSDL.
This is a sample request that I sent (intercepted using Fiddler):
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPo3vYq2eC/5VIuiUcm2hEtw8AABBBJr/dLQF7z02Y7UKwphq24W1n9j0XlQ1MiAlOjy5fO14ACQAA</VsDebuggerCausalityData>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GetCustomerProfile xmlns="https://api.authorize.net/soap/v1/">
<merchantAuthentication>
<name>95U6bwXXXXX</name>
<transactionKey>8tf62gV7XXXXXX</transactionKey>
</merchantAuthentication>
<customerProfileId>37745529</customerProfileId>
</GetCustomerProfile>
</s:Body>
</s:Envelope>
This is the response:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetCustomerProfileResponse xmlns="https://api.authorize.net/soap/v1/">
<GetCustomerProfileResult>
<resultCode>Ok</resultCode>
<messages>
<MessagesTypeMessage>
<code>I00001</code>
<text>Successful.</text>
</MessagesTypeMessage>
</messages>
<profile>
<merchantCustomerId>33938</merchantCustomerId>
<email>4691705#EXAMPLE.COM</email>
<customerProfileId>37745529</customerProfileId>
<paymentProfiles>
<CustomerPaymentProfileMaskedType>
<billTo>
<firstName>TEST</firstName>
<lastName>USER</lastName>
<company>Defender Razor</company>
<address>1 RODEO DRIVE</address>
<city>BEVERLY HILLS</city>
<state>CA</state>
<zip>90210</zip>
<country>UNITED STATES</country>
</billTo>
<customerProfileId>0</customerProfileId>
<customerPaymentProfileId>34313485</customerPaymentProfileId>
<payment>
<creditCard>
<cardNumber>XXXX5108</cardNumber>
<expirationDate>XXXX</expirationDate>
</creditCard>
</payment>
</CustomerPaymentProfileMaskedType>
</paymentProfiles>
</profile>
</GetCustomerProfileResult>
</GetCustomerProfileResponse>
</soap:Body>
</soap:Envelope>
Everything here is correct - as you can see the payment node is being sent correctly.
However - with .NET deserialization the order of attributes matters - as specified in the generated References.cs file.
[System.Xml.Serialization.XmlElementAttribute(Order=0)]
It turns out that two new fields were added to the response billTo and customerProfileId but they weren't added to the WSDL.
So when trying to deserialize the field billTo is found but that isn't what was expected - so everything ends up null.
If you add these two lines (and be careful to add them to exactly this type) then you can regenerate the references.cs file (by right clicking on the service reference and regenerating the file).
If you were generating your proxy from the URL https://api.authorize.net/soap/v1/Service.asmx?WSDL then you will need to download this file locally as Service.wsdl and generate the proxy from there.
<s:element minOccurs="1" maxOccurs="1" name="billTo" type="tns:CustomerAddressType"/>
<s:element minOccurs="1" maxOccurs="1" name="customerProfileId" type="s:long" />
<s:complexType name="CustomerPaymentProfileMaskedType">
<s:complexContent mixed="false">
<s:extension base="tns:CustomerPaymentProfileBaseType">
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="billTo" type="tns:CustomerAddressType"/>
<s:element minOccurs="1" maxOccurs="1" name="customerProfileId" type="s:long" />
<s:element minOccurs="1" maxOccurs="1" name="customerPaymentProfileId" type="s:long" />
<s:element minOccurs="0" maxOccurs="1" name="payment" type="tns:PaymentMaskedType" />
<s:element minOccurs="0" maxOccurs="1" name="driversLicense" type="tns:DriversLicenseMaskedType" />
<s:element minOccurs="0" maxOccurs="1" name="taxId" type="s:string" />
</s:sequence>
</s:extension>
</s:complexContent>
</s:complexType>
I lost over 12 hours of payments before this was detected. Fortunately I have the customer's emails but this was very bad. You can't just add fields to a response where the order matters. And even worse than that you can't just forget to add them to the WSDL.
This was the quick fix for me. I may switch to using the proper API at some point - and I've reported this to Authorize.net hoping they may respond too.
This is the differences in References.cs after I made my change. As you can see the Order property has been incremented :

Call RPC/encoded Webservice with Apache Camel and CXF Endpoint

There is a lot of information about Apache Camel + CXF-Endpoint and RPC/encoded legacy webservices.
But until now I did not find a solution for the problem.
I want to call an RPC/encoded webservice from Apache Camel over the CXF endpoint.
CXF does not support RPC/encoded Webservices.
So I tried two approaches to solve the problem.
Convert wsdl from RPC/encoded to RPC/literal and generate source files.
Call the webservice in RPC/literal style which is supported by CXF.
The following article suggests that this approach could be a solution for my problem: Best way to consume RPC/encoded webservice?
Send the complete SOAP-Message without mapping to objects (no JAXB).
Neither approach 1 nor approach 2 works.
In the following sections I will explain my approaches and the problems in more detail.
Prerequisites
Apache Tomcat 7
Apache Camel 2.14.1
Apache CXF 2.7.10
Webservice Endpoint is mocked with SOAP-UI 5.0.0 on http://localhost:9000/myfunctionalmock
First approach: Convert wsdl RPC/encoded to RPC/literal and generate sources
In the RCP/encoded wsdl I have changed following:
WSDL Bindings:
<wsdl:binding name="exampleSoapBinding" type="impl:MyFunctionalWebservices">
<wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="isAlive">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="isAliveRequest">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://my.example.com/myFunction" use="encoded"/>
</wsdl:input>
...
to
<wsdl:binding name="exampleSoapBinding" type="impl:MyFunctionalWebservices">
<wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="isAlive">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="isAliveRequest">
<wsdlsoap:body namespace="http://my.example.com/myFunction" use="literal"/>
</wsdl:input>
…
Arrays of Objects:
<complexType name="ArrayOfMyElement">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="impl:MyElement[]"/>
</restriction>
</complexContent>
</complexType>
to
<complexType name="ArrayOfMyElement">
<xsd:sequence>
<xsd:element name="MyElement"
type="impl:MyElement"
minOccurs="0"
maxOccurs="unbounded"/>
</xsd:sequence>
</complexType>
Arrays of simple types:
<complexType name="ArrayOf_xsd_string">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
</restriction>
</complexContent>
</complexType>
to
<complexType name="ArrayOf_xsd_string">
<xsd:sequence>
<xsd:element name="item"
type="xsd:string"
minOccurs="0"
maxOccurs="unbounded"/>
</xsd:sequence>
</complexType>
Arrays of undefined Type (anyType):
<complexType name="ArrayOf_xsd_anyType">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:anyType[]"/>
</restriction>
</complexContent>
</complexType>
to
<complexType name="ArrayOf_xsd_anyType">
<xsd:sequence>
<xsd:element name="item"
type="xsd:anyType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</complexType>
After that I have generated source files with IntelliJ Webservice plugin (over CXF wsdl2java)
In Camel I have configured following Endpoint:
CxfEndpoint endpoint = new CxfEndpoint();
endpoint.setAddress("http://127.0.0.1:9000/myfunctionalmock");
endpoint.setWsdlURL("wsdl/myservice_literal.wsdl");
endpoint.setServiceClass("com.my.example.MyFunctionalWebservices");
endpoint.setEndpointNameString("{http://my.example.com/myFunction}rpcrouter");
endpoint.setServiceNameString("{http://my.example.com/myFunction}MyFunctionalWebservicesService");
endpoint.setDataFormat(DataFormat.POJO);
endpoint.setSynchronous(true);
endpoint.setCamelContext(camelContext);
endpoint.setEndpointUriIfNotSpecified(MY_ENDPOINT_URL);
camelContext.addEndpoint(MY_ENDPOINT_URL, endpoint);
Usage of CXF-Endpoint in Camel route:
I want to call following function of webservice:
public Result isAlive(java.lang.String identifier);
The timer in the camel route is only for triggering the webservice.
from("timer://myTimer?period=10000")
.log(LoggingLevel.INFO, "START Timer Webservice.")
.setBody().constant("1620000018")
.setHeader("operationName", constant("isAlive"))
.setHeader("operationNamespace", constant("http://my.example.com/myFunction"))
.to(MyCamelConfiguration.MY_ENDPOINT_URL);
Problems with this approach:
At runtime following message appears at deployment time:
2015-03-05 09:57:46,659; 2010; [localhost-startStop-1]; DEBUG; wsdl11.WSDLServiceBuilder; Operation {http://my.example.com/myFunction}isAlive cannot be unwrapped, input message must reference global element declaration with same localname as operation
Following exception occurs at runtime:
org.apache.cxf.binding.soap.SoapFault: No namespace on "HTML" element. You must send a SOAP request.
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.readVersion(ReadHeadersInterceptor.java:111)
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:155)
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:835)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1614)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1504)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1310)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:628)
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:565)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:474)
at org.apache.camel.component.cxf.CxfProducer.process(CxfProducer.java:149)
at org.apache.camel.impl.SynchronousDelegateProducer.process(SynchronousDelegateProducer.java:62)
at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:120)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:72)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:416)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:118)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:80)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.component.timer.TimerConsumer.sendTimerExchange(TimerConsumer.java:166)
at org.apache.camel.component.timer.TimerConsumer$1.run(TimerConsumer.java:74)
at java.util.TimerThread.mainLoop(Timer.java:512)
at java.util.TimerThread.run(Timer.java:462)
Second approach: Send the SOAP-Message without mapping to Objects.
Endpoint definition in Camel:
CxfEndpoint endpoint = new CxfEndpoint();
endpoint.setAddress("http://127.0.0.1:9000/myfunctionalmock");
endpoint.setEndpointNameString("{http://my.example.com/myFunction}rpcrouter");
endpoint.setServiceNameString("{http://my.example.com/myFunction}MyFunctionalWebservicesService");
endpoint.setDataFormat(DataFormat.RAW);
endpoint.setWrappedStyle(false);
endpoint.setSynchronous(true);
endpoint.setCamelContext(camelContext);
endpoint.setEndpointUriIfNotSpecified(MY_TEMPLATE_ENDPOINT_URL);
camelContext.addEndpoint(MY_TEMPLATE_ENDPOINT_URL, endpoint);
Usage in route:
from("timer://myTimer?period=10000")
.log(LoggingLevel.INFO, "START Timer Webservice.")
.setBody().constant(
"<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:myns=\"http://my.example.com/myFunction\">\n" +
" <soapenv:Header/>\n" +
" <soapenv:Body>\n" +
" <myns:isAlive soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" +
" <identifier xsi:type=\"xsd:string\">1620000018</identifier>\n" +
" </myns:isAlive>\n" +
" </soapenv:Body>\n" +
"</soapenv:Envelope>"
)
.to(MyCamelConfiguration.MY_TEMPLATE_ENDPOINT_URL)
.log(LoggingLevel.INFO, "END Timer Webservice.")
.log(LoggingLevel.INFO, "Body after ws call = ${body}");
But the webservice on http://localhost:9000/myfunctionalmock is never called.
I found following log messages in logfile:
2015-03-05 10:56:35,522; 12843; [Camel (camel-1) thread #0 - timer://myTimer]; DEBUG; phase.PhaseInterceptorChain; Invoking handleMessage on interceptor org.apache.cxf.jaxb.attachment.JAXBAttachmentSchemaValidationHack#1d3694a
2015-03-05 10:56:35,523; 12844; [Camel (camel-1) thread #0 - timer://myTimer]; DEBUG; phase.PhaseInterceptorChain; Invoking handleMessage on interceptor org.apache.cxf.ws.policy.PolicyVerificationInInterceptor#1a0ff10
2015-03-05 10:56:35,523; 12844; [Camel (camel-1) thread #0 - timer://myTimer]; DEBUG; policy.PolicyVerificationInInterceptor; Verified policies for inbound message.
2015-03-05 10:56:35,523; 12844; [Camel (camel-1) thread #0 - timer://myTimer]; INFO ; helpers.MarkerIgnoringBase; END Timer Webservice.
2015-03-05 10:56:35,523; 12844; [Camel (camel-1) thread #0 - timer://myTimer]; INFO ; helpers.MarkerIgnoringBase; Body after ws call = <HTML>
<HEAD><TITLE>Redirection</TITLE></HEAD>
<BODY><H1>Redirect</H1></BODY>
Both approaches do not work.Is there a possibility to call RPC/encoded webservice over CXF in Camel?
Thanks in advance.
Regards,
Max
As you say Apache CXF does not support the old RPC style. You would need to use an older WS library such as Apache Axis 1.x. There is no Camel component for that, but as its all just java code, you can write some java code that uses Axis 1.x, and then let Camel call the java code, using its bean component / processor.
http://camel.apache.org/bean
Another alternative is that as SOAP is over HTTP you can just use Camel's HTTP components also. But you would need to build the message body and headers according to the RPC style, but that should not be so hard either to do.

Why wsimport tool for generating files from wsdl file not working showing error code 400

I am working on webservices to integrate with the application and as a newbee needs more input.
Can any anyone tell me the issue why wsimport throws error on console : Server returned HTTP response code: 400 for URL:
http://localhost:8084/service/HelloWorld.wsdl
Following is my code below :
HelloWorld.java
//Service Endpoint Interface
#WebService
#SOAPBinding(style = Style.RPC)
public interface HelloWorld {
#WebMethod String getHelloWorldAsString(String msg);
}
HelloWorldImpl.java
#WebService(endpointInterface = "com.pack.service.HelloWorld")
public class HelloWorldImpl implements HelloWorld{
#Override
public String getHelloWorldAsString(String msg) {
return "Hello, "+msg+ " How are you ?" ;
}
}
HelloWorldPublisher.java
//Endpoint Publisher
public class HelloWorldPublisher {
public static void main(String[] args){
System.out.println("Webservice Running ... ");
Endpoint.publish("http://localhost:8084/service/HelloWorld", new HelloWorldImpl());
}
}
Now, when i want to generate stub files from wsdl file. It gives the following error :
Note : Using command prompt and entering the following on command line :
wsimport -keep http://localhost:8084/service/HelloWorld?wsdl
At command line it shows >>
D:\Personal\WebService>wsimport -keep http://localhost:8084/service/HelloWorld?wsdl
parsing WSDL...
[ERROR] Server returned HTTP response code: 400 for URL: http://localhost:8084/service/HelloWorld?wsdl
Failed to read the WSDL document: http://localhost:8084/service/HelloWorld?wsdl, because 1) could not find the document; /2) the document could not be read; 3) the root element of the document is not
<wsdl:definitions>.
[ERROR] failed.noservice=Could not find wsdl:service in the provided WSDL(s):
At least one WSDL with at least one service definition needs to be provided.
Failed to parse the WSDL.
D:\Personal\WebService>
wsdl file >>.
<?xml version="1.0" encoding="UTF-8"?>
<!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2-hudson-740-. -->
<!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2-hudson-740-. -->
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://service.pack.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://service.pack.com/" name="HelloWorldImplService">
<types/>
<message name="getHelloWorldAsString">
<part name="arg0" type="xsd:string"/>
</message>
<message name="getHelloWorldAsStringResponse">
<part name="return" type="xsd:string"/>
</message>
<portType name="HelloWorld">
<operation name="getHelloWorldAsString">
<input wsam:Action="http://service.pack.com/HelloWorld/getHelloWorldAsStringRequest" message="tns:getHelloWorldAsString"/>
<output wsam:Action="http://service.pack.com/HelloWorld/getHelloWorldAsStringResponse" message="tns:getHelloWorldAsStringResponse"/>
</operation>
</portType>
<binding name="HelloWorldImplPortBinding" type="tns:HelloWorld">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/>
<operation name="getHelloWorldAsString">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal" namespace="http://service.pack.com/"/>
</input>
<output>
<soap:body use="literal" namespace="http://service.pack.com/"/>
</output>
</operation>
</binding>
<service name="HelloWorldImplService">
<port name="HelloWorldImplPort" binding="tns:HelloWorldImplPortBinding">
<soap:address location="http://localhost:8084/service/HelloWorld"/>
</port>
</service>
</definitions>
I had the exact same issue when trying to generate the client side from the command line. After switching of my proxy settings, the error went away and I successfully generated the client files.
Disable Proxy Settings.

Axis2 Adb Client Basic Auth over https secure url

I have serached this question on Stackoverflow and found some similar questions but none of them solved my issue. I have compiled all the "proposed" solution but NOTHING works :-(
I have a wsdl and I generated the client code using adb client(Axis 2). The wsdl says that this request will be sent over Https url. I able to successfully create a stub using wsdl to java. However I am not sure how to Basic authentication. The documentation which tells me the details also says that I user name and pwd should be encoded using Base64.
The authentication method used is HTTP Basic . The user name and
password will need to be encoded in a base64 format – UTF8 character
set.
Example: Username:Password = “VXNlcm5hbWU6UGFzc3dvcmQ=”
BTW I have tried this wsdl in SOAP UI and and I am getting correct response but some how my java code won't work
Now Here is the wsdl
<?xml version="1.0" encoding="UTF-8"?>
<definitions targetNamespace="urn:OTSB2B" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="urn:OTSB2B" xmlns:intf="urn:OTSB2B" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<schema targetNamespace="urn:OTSB2B" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:urn="urn:OTSB2B">
<simpleType name="tn">
<restriction base="string">
<length value="10"/>
</restriction>
</simpleType>
<simpleType name="prov">
<restriction base="string">
<length value="2"/>
<enumeration value="on"/>
<enumeration value="qc"/>
</restriction>
</simpleType>
<element name="getPresaleByTN">
<complexType>
<sequence>
<element name="tn" type="urn:tn"/>
<element name="prov" type="urn:prov"/>
</sequence>
</complexType>
</element>
<element name="getPresaleByTNReturn" type="xsd:string"/>
<element name="isAlive"/>
<element name="isAliveReturn" type="xsd:boolean"/>
</schema>
</wsdl:types>
<message name="isAliveRequest">
<part element="impl:isAlive" name="isAlive"/>
</message>
<message name="getPresaleByTNRequest">
<part element="impl:getPresaleByTN" name="getPresaleByTN"/>
</message>
<message name="isAliveResponse">
<part element="impl:isAliveReturn" name="isAliveReturn"/>
</message>
<message name="getPresaleByTNResponse">
<part element="impl:getPresaleByTNReturn" name="getPresaleByTNReturn"/>
</message>
<portType name="GetPresaleByTN">
<operation name="getPresaleByTN">
<input message="impl:getPresaleByTNRequest" name="getPresaleByTNRequest"/>
<output message="impl:getPresaleByTNResponse" name="getPresaleByTNResponse"/>
</operation>
<operation name="isAlive">
<input message="impl:isAliveRequest" name="isAliveRequest"/>
<output message="impl:isAliveResponse" name="isAliveResponse"/>
</operation>
</portType>
<binding name="DominoSoapBinding" type="impl:GetPresaleByTN">
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="getPresaleByTN">
<wsdlsoap:operation soapAction=""/>
<input name="getPresaleByTNRequest">
<wsdlsoap:body use="literal"/>
</input>
<output name="getPresaleByTNResponse">
<wsdlsoap:body use="literal"/>
</output>
</operation>
<operation name="isAlive">
<wsdlsoap:operation soapAction=""/>
<input name="isAliveRequest">
<wsdlsoap:body use="literal"/>
</input>
<output name="isAliveResponse">
<wsdlsoap:body use="literal"/>
</output>
</operation>
</binding>
<service name="GetPresaleByTNService">
<port binding="impl:DominoSoapBinding" name="Domino">
<wsdlsoap:address location="https://b2b.ivv.bell.ca/ots-qualification-service-tn"/>
</port>
</service>
</definitions>
I have tried this:
GetPresaleByTNServiceStub stub = new GetPresaleByTNServiceStub();
ServiceClient client = stub._getServiceClient();
client.addStringHeader(new QName("userName"), "XXX");
client.addStringHeader(new QName("password"), "YYYYYYYY");
GetPresaleByTNServiceStub.GetPresaleByTN request = new GetPresaleByTN();
Tn tn = new Tn();
tn.setTn("4164390001");
request.setTn(tn);
request.setProv(Prov.on);
GetPresaleByTNReturn response = stub.getPresaleByTN(request);
System.out.println(response.getGetPresaleByTNReturn());
This gives me following error:
org.apache.axis2.AxisFault: Failed to add string header, you have to
have namespaceURI for the QName at
org.apache.axis2.client.ServiceClient.addStringHeader(ServiceClient.java:434)
at com.dinesh.bellAxis.App.main(App.java:30)
Then I tried this
GetPresaleByTNServiceStub stub = new GetPresaleByTNServiceStub();
ServiceClient client = stub._getServiceClient();
HttpTransportProperties.Authenticator basicAuth = new HttpTransportProperties.Authenticator();
basicAuth.setUsername("XXX");
basicAuth.setPassword("CCCCC");
basicAuth.setPreemptiveAuthentication(true);
stub._getServiceClient().getOptions().setProperty(HTTPConstants.AUTHENTICATE, basicAuth);
GetPresaleByTNServiceStub.GetPresaleByTN request = new GetPresaleByTN();
Tn tn = new Tn();
tn.setTn("4164390001");
request.setTn(tn);
request.setProv(Prov.on);
GetPresaleByTNReturn response = stub.getPresaleByTN(request);
System.out.println(response.getGetPresaleByTNReturn());
This gives me the following error:
org.apache.axis2.AxisFault: Transport level information does not match
with SOAP Message namespace URI at
org.apache.axis2.AxisFault.makeFault(AxisFault.java:430) at
org.apache.axis2.transport.TransportUtils.createSOAPMessage(TransportUtils.java:90)
at
org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:353)
at
org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:416)
at
org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:228)
at
org.apache.axis2.client.OperationClient.execute(OperationClient.java:163)
at
com.acn.client.GetPresaleByTNServiceStub.getPresaleByTN(GetPresaleByTNServiceStub.java:460)
Next I tried this: which I think is incorrect as it WS Security and not basic auth but what the heck I exhausted all my options
GetPresaleByTNServiceStub stub = new GetPresaleByTNServiceStub();
ServiceClient client = stub._getServiceClient();
OMFactory omFactory = OMAbstractFactory.getOMFactory();
OMElement omSecurityElement = omFactory.createOMElement(new QName( "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security", "wsse"), null);
OMElement omusertoken = omFactory.createOMElement(new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "UsernameToken", "wsu"), null);
OMElement omuserName = omFactory.createOMElement(new QName("", "Username", "wsse"), null);
omuserName.setText("XXXX");
OMElement omPassword = omFactory.createOMElement(new QName("", "Password", "wsse"), null);
omPassword.addAttribute("Type","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText",null );
omPassword.setText("YYYYYYY");
omusertoken.addChild(omuserName);
omusertoken.addChild(omPassword);
omSecurityElement.addChild(omusertoken);
stub._getServiceClient().addHeader(omSecurityElement);
GetPresaleByTNServiceStub.GetPresaleByTN request = new GetPresaleByTN();
Tn tn = new Tn();
tn.setTn("4164390001");
request.setTn(tn);
request.setProv(Prov.on);
GetPresaleByTNReturn response = stub.getPresaleByTN(request);
System.out.println(response.getGetPresaleByTNReturn());
This gives the following error:
Exception in thread "main" java.lang.IllegalArgumentException: Cannot
create a prefixed element with an empty namespace name at
org.apache.axiom.om.impl.llom.OMElementImpl.handleNamespace(OMElementImpl.java:186)
at
org.apache.axiom.om.impl.llom.OMElementImpl.(OMElementImpl.java:161)
at
org.apache.axiom.om.impl.llom.factory.OMLinkedListImplFactory.createOMElement(OMLinkedListImplFactory.java:126)
at com.dinesh.bellAxis.App2.main(App2.java:37)
I am not sure what to do next and have checked all the documentation on Apache Axis2 and googled all over the place but could get the code to work.
Any suggestions
Code fragments 1 and 3 don't work because they attempt to create a message that is invalid with respect to SOAP (fragment 1) or XML (fragment 3). Anyway, they attempt to add SOAP headers to the message, which is not what basic auth is about.
Code fragment 2 looks correct. From the stack trace of the exception (more precisely the presence of the handleResponse method) you can see that there is an issue with the response. The error message likely indicates that the content type of the response doesn't match the SOAP version actually used in the response. This means that there is a problem with the service, not with the client.
I found the answer after a lot of trial and error and going over SAAj tutorial on Oracle website.
I able to do Basic authentication using this
String authorization = new sun.misc.BASE64Encoder().encode((“myUserName”+”:”+”myPassword”).getBytes());
headers.addHeader(“Authorization”, “Basic ” + authorization);
Here's the complete tutorial - http://www.javahabit.com/2014/10/17/quick-tutorial-saaj-api/