Add ws-security to flow in Mule - web-services

I am using mule without anypoint studio.
Exposed webservice in mule. Client sends a request, I transform the message (f.e. fill in some fields) and forward it to the external webservice (not managed by me).
Java classes for the external webservice were created using wsimport based on their wsdl
They require wss xml signature based on the keystore they gave me
Their service (and wsdl) is accessible via https
My goal: I want to add ws-security (just Signature action for now) in order to be able to make requests to their WS.
In conclusion: Client sends a request to WS on the mule I own (http), I transform it,
add ws-security and send it to the external webservice (https).
This is my WS:
#WebService
public interface LFlow {
#WebMethod
String exec(#WebParam(name = "pname") String pname,
#WebParam(name = "mname") String mname,
#WebParam(name = "parameters") String parameters);
}
And the request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:abc="http://a.b.c/">
<soapenv:Header/>
<soapenv:Body>
<abc:exec>
<pname>B</pname>
<mname>getC</mname>
<parameters>smth</parameters>
</abc:exec>
</soapenv:Body>
</soapenv:Envelope>
This is mule config I have for that:
<?xml version="1.0" encoding="UTF-8"?>
<mule <!--(...)--> >
<context:property-placeholder location="classpath:l.properties, classpath:wss.properties"
ignore-resource-not-found="true"/>
(...)
<flow name="lFlow">
<!-- Defined in other place: <http:connector name="domain-http-connector" /> -->
<http:inbound-endpoint connector-ref="domain-http-connector" address="${l.bind.address}" exchange-pattern="request-response"
doc:name="HTTP">
<cxf:jaxws-service serviceClass="a.b.c.LFlow" mtomEnabled="true">
<cxf:outFaultInterceptors>
<spring:bean class="a.b.c.interceptors.FaultSoapInterceptor"/>
</cxf:outFaultInterceptors>
</cxf:jaxws-service>
</http:inbound-endpoint>
<choice doc:name="Forward to proper process">
<!--(...)-->
<when expression="#[payload[0] == 'B']">
<flow-ref name="b" doc:name="b"/>
</when>
</choice>
</flow>
<!--(...)-->
<sub-flow name="b">
<choice doc:name="forward to proper method">
<!--(...)-->
<when expression="#[payload[1] == 'getC']">
<invoke object-ref="aHandler" method="getC" doc:name="Get C element"
methodArgumentTypes="java.lang.String" methodArguments="#[payload[2]]"/>
</when>
</choice>
</sub-flow>
</mule>
the wss.properties file is in the src/main/resources directory and looks like this:
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin

> org.apache.ws.security.crypto.merlin.keystore.type=jks

> org.apache.ws.security.crypto.merlin.keystore.password=pass

> org.apache.ws.security.crypto.merlin.keystore.alias=alias
org.apache.ws.security.crypto.merlin.file=path-to-keystore
handler on my side that does some transformations (not in this exmaple for simplicity):
#Component
public class AHandler {
private final AService aService;
#Autowired
public AHandler(final AService aService) {
this.aService = aService;
}
public GetCResponse getC(final String jsonPayload) {
return aService.getC(mapToGetCRequest(jsonPayload));
}
}
then it is routed to the class that is supposed to send it to the external web-service:
#Service
public class AServiceImpl implements AService {
// (...)
#Override
public GetCResponse getC(final GetCRequest request) {
return getInstance().getC(request);
}
private BInterface getInstance() {
/**
I have generated *.jar for the external B service using wsimport from their wsdl-url
*/
final B service = new B();
final BInterface port = service.getBSOAP();
final BindingProvider bindingProvider = (BindingProvider) port;
final Map<String, Object> context = bindingProvider.getRequestContext();
context.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, /*wsdl-url*/);
context.put("thread.local.request.context", "true");
return port;
}
}
and this is part of the wsdl:
(...) <?xml name=B>
</wsdl:types>
<wsdl:message name="GetCRequest">
<wsdl:part element="b:GetCRequest" name="payload">
</wsdl:part>
</wsdl:message>
<wsdl:message name="GetCResponse">
<wsdl:part element="b:GetCResponse" name="payload">
</wsdl:part>
<wsdl:portType name="BInterface">
<wsdl:operation name="getC">
<wsdl:input message="b:GetCRequest">
</wsdl:input>
<wsdl:output message="b:GetCResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="BSOAPBinding" type="b:BInterface">
<soap:binding style="b" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getC">
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="B">
<wsdl:port binding="b:BSOAPBinding" name="BSOAP">
<soap:address location="https://b.local/cxf/ba/b"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Communication works in soapui. I added outgoing ws-security configuration, added "signature" entry, chosen previously added keystore, with alias and password, and there it works. But I can't make it work in mule, hence the question.
As far as I know, I should either:
create WSS4JOutInterceptor with configured: action, signatureUser, signaturePropFile, passwordCallbackRef and somehow connect it with mule outgoing messages or
add <jaxws-client> or <proxy-client> with wss config embedded:
<cxf:ws-security>
<cxf:ws-config>
<cxf:property key="action" value="Signature"/>
<cxf:property key="signaturePropFile" value="wss.properties"/>
<cxf:property key="passwordCallbackClass" value="com.mulesoft.mule.example.security.PasswordCallback"/>
</cxf:ws-config>
</cxf:ws-security>
But I just can't make it work. I would really appreciate any help
Edited (24.08.2021T12:03:00Z):
Mule sdk 3.8.0
To answer what happens when I apply my solutions is complicated. I am not sure where exactly I should put the wss config. Should I use <jaxws-client> or <proxy-client> ? should it be in the <subflow> or <flow> ? what "attributes" to these elements I should pass (bare minimum, required to test if it even works) ? or maybe I should use <cxf:inInterceptors>/<cxf:outInterceptors> ?
I tried different configurations but I am not sure if I did it the right way, so the errors I was getting were probably results of my improper use. So I didn't put them here, cause they might make it harder to read my question.
Edited (24.08.2021T12:54:00Z):
But according to the doc:
proxy-client provides raw SOAP and WS-* processing for outgoing XML
messages, allowing you to send outgoing messages in raw XML form and
apply things like WS-Security to them.
I should use <proxy-client> and I believe it should be in the "subflow":
<sub-flow name="b">
<cxf:proxy-client>
<cxf:ws-security>
<cxf:ws-config>
<cxf:property key="action" value="Signature"/>
<cxf:property key="signatureUser" value="keystore-alias"/>
<cxf:property key="signaturePropFile" value="wss.properties"/>
<cxf:property key="passwordCallbackClass" value="com.mulesoft.mule.example.security.PasswordCallback"/>
</cxf:ws-config>
</cxf:ws-security>
</cxf:proxy-client>
<choice doc:name="forward to proper method">
<!--(...)-->
<when expression="#[payload[1] == 'getC']">
<invoke object-ref="aHandler" method="getC" doc:name="Get C element"
methodArgumentTypes="java.lang.String" methodArguments="#[payload[2]]"/>
</when>
</choice>
</sub-flow>
Is that correct ? what attributes should I define for <cxf:proxy-client> ? or maybe instead of defining <cxf:ws-security> inside, I should define interceptors like this:
<bean id="clientWss4jOutInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
<constructor-arg>
<map>
<entry key="action" value="Signature"/>
<entry key="signatureUser" value=""/>
<entry key="signaturePropFile" value=""/>
<entry key="passwordCallbackRef" value-ref=""/>
</map>
</constructor-arg>
</bean>
(...)
<sub-flow name="b">
<cxf:proxy-client doc:name="Proxy client">
<cxf:outInterceptors>
<spring:bean id="clientWss4jOutInterceptor">
</spring:bean>
</cxf:outInterceptors>
</cxf:proxy-client>
(...)
Edited (25.08.2021T11:28:00Z):
When try to use consumer like this (mule-config.xml):
<?xml version="1.0" encoding="UTF-8"?>
<mule
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tls="http://www.mulesoft.org/schema/mule/tls"
version="CE-3.8.0"
xmlns:ws="http://www.mulesoft.org/schema/mule/ws"
(...)
<tls:context name="tlsContext">
<tls:key-store
path="C:\\Users\\john\\Documents\\integrationB.keystore"
keyPassword="privatekey-password"
password="keystore-password"
alias="alias" />
</tls:context>
<!--service, port, wsdl-url, address - all taken from wsdl-->
<ws:consumer-config
name="WebServiceConsumer"
serviceAddress="https://b.local/cxf/ba/b"
wsdlLocation="https://b.local/cxf/ba/b?wsdl"
service="B"
port="BSOAP">
<ws:security>
<ws:wss-sign tlsContext-ref="tlsContext" />
</ws:security>
</ws:consumer-config>
<flow name="lFlow">
<http:inbound-endpoint
connector-ref="domain-http-connector"
address="${l.bind.address}"
exchange-pattern="request-response"
doc:name="HTTP">
<cxf:jaxws-service serviceClass="a.b.c.LFlow" mtomEnabled="true">
<cxf:outFaultInterceptors>
<spring:bean class="a.b.c.interceptors.FaultSoapInterceptor"/>
</cxf:outFaultInterceptors>
</cxf:jaxws-service>
</http:inbound-endpoint>
<http:listener config-ref="HTTP_Listener_Configuration" path="*" doc:name="HTTP">
<http:response-builder statusCode="200"/>
</http:listener>
<ws:consumer config-ref="WebServiceConsumer" operation="getC" doc:name="Get C element"/>
<choice doc:name="Forward to proper process">
<!--(...)-->
<when expression="#[payload[0] == 'B']">
<flow-ref name="b" doc:name="b"/>
</when>
</choice>
</flow>
<!--(...)-->
<sub-flow name="b">
<choice doc:name="forward to proper method">
<!--(...)-->
<when expression="#[payload[1] == 'getC']">
<invoke object-ref="aHandler" method="getC" doc:name="Get C element"
methodArgumentTypes="java.lang.String" methodArguments="#[payload[2]]"/>
</when>
</choice>
</sub-flow>
</mule>
I get during app-start:
Caused by:
org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException:
Line 46 in XML document from URL [file:/(...)/mule-config.xml] is
invalid; nested exception is org.xml.sax.SAXParseException;
lineNumber: 46; columnNumber: 61; cvc-complex-type.2.4.a: Invalid
content was found starting with element 'ws:consumer-config'. One of
(...) is expected.
46:61 points to the last charatcer of: port="BSOAP">.

If possible I would avoid using CXF and try the Web Service Consumer that it is much easier to use:
<tls:context name="tlsContext">
<tls:key-store path="path" keyPassword="pass" password="pass" alias="keyalias" />
</tls:context>
<ws:consumer-config name="Web_Service_Consumerweather" serviceAddress="http://localhost/test" wsdlLocation="Test.wsdl"
service="TestService" port="TestPort">
<ws:security>
<ws:wss-sign tlsContext-ref="tlsContext" />
</ws:security>
</ws:consumer-config>
<flow name="listInventory" doc:name="listInventory">
<http:listener config-ref="HTTP_Listener_Configuration" path="inventory" doc:name="HTTP">
<http:response-builder statusCode="200"/>
</http:listener>
<ws:consumer config-ref="Web_Service_Consumer" operation="ListInventory" doc:name="List Inventory"/>
</flow>
Also note that Mule 3.8 has been replaced by Mule 3.9. The latest release is Mule 4.3 which is not compatible with Mule 3.x and doesn't support CXF.
Documentation: https://docs.mulesoft.com/web-service-consumer-connector/0.3.9/

Related

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.

Mule ESB - how to pass multi parameter to soap web service in browser

I just have a little experience with Mule ESB 3.5, and I found that most of Mule examples only create SOAP Web Service with one parameter. For example, you can see that in SOAP Web Service Security example.
http://www.mulesoft.org/documentation/display/current/SOAP+Web+Service+Security+Example
So I have one question, acroding to above example, after using CHOICE flow control, how to pass multi parameter to method of SOAP web service.
Some suggests for me is to use object array to pass multi parameter, but I still have no clue at all.
Thanks to David. I just try your suggestion. But I think I should update my question to make it clearly.
Firstly, I create web service
#WebService
public interface Greeter
{
public String greet(String name);
public String welcome( String name1,String name2);
}
Then I have a control flow for web service configuration
<flow name="UnsecureServiceFlow" doc:name="UnsecureServiceFlow">
<http:inbound-endpoint address="http://localhost:63081/services/unsecure" exchange-pattern="request-response" doc:name="HTTP Inbound Endpoint"/>
<cxf:jaxws-service serviceClass="com.mulesoft.mule.example.security.Greeter" doc:name="Unsecure service"/>
<component class="com.mulesoft.mule.example.security.GreeterService" doc:name="Greeter Service" />
</flow>
Next is the sub flow using jax-ws client to call the method of web service
<flow name="SecurityClients" doc:name="SecurityClients">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="63080" path="client" doc:name="HTTP Inbound Endpoint"/>
<set-payload value="#[message.inboundProperties['http.query.params']['name']]" doc:name="Set payload with 'name' query param"/>
<set-variable variableName="clientType" value="#[message.inboundProperties['http.query.params']['clientType']]" doc:name="Set clientType"/>
<choice doc:name="Choice">
<when expression="#[clientType == 'unsecure']">
<flow-ref name="unsecure" doc:name="Invoke unsecure sub-flow"/>
</when>
<when expression="#[clientType == 'usernameToken']">
<flow-ref name="usernameToken" doc:name="Invoke usernameToken sub-flow"/>
</when>
<when expression="#[clientType == 'usernameTokenSigned']">
<flow-ref name="usernameTokenSigned" doc:name="Invoke usernameToken Signed sub-flow"/>
</when>
<when expression="#[clientType == 'usernameTokenEncrypted']">
<flow-ref name="usernameTokenEncrypted" doc:name="Invoke usernameToken Encrypted sub-flow"/>
</when>
<when expression="#[clientType == 'samlToken']">
<flow-ref name="samlToken" doc:name="Invoke samlToken sub-flow"/>
</when>
<when expression="#[clientType == 'samlTokenSigned']">
<flow-ref name="samlTokenSigned" doc:name="Invoke samlToken Signed sub-flow"/>
</when>
<otherwise>
<set-payload value="Client type is not supported" doc:name="Client type is not supported"/>
</otherwise>
</choice>
<set-property propertyName="Content-Type" value="text/plain" doc:name="Set response Content-Type"/>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<set-payload value="There has been an Error processing the request" doc:name="Set Payload"/>
<set-property propertyName="Content-Type" value="text/plain" doc:name="Set response Content-Type"/>
</catch-exception-strategy>
</flow>
<sub-flow name="unsecure" doc:name="unsecure">
<cxf:jaxws-client operation="greet" serviceClass="com.mulesoft.mule.example.security.Greeter" doc:name="Unsecure SOAP client" doc:description="Unsecure SOAP client"/>
<http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="63081" path="services/unsecure" doc:name="Invoke unsecure Web Service"/>
</sub-flow>
It's ok to use that address to invoke greet method, it only has one parameter.
localhost:63080/client?clientType=usernameToken&name=John
However when I change greet method to welcome method, I do not know how to pass more parameter to it or have to change anything , because payload only contains name parameter
Generate the JAX-WS client classes from the remote web service WSDL and use them in a cxf:jaxws-client configuration element.
In your case, you need to set-payload inside each when in order to create the request object that is needed by cxf:jaxws-client.
Suppose that you need to create a org.saml.SamlToken object for the samlToken case, you would do:
<set-payload value="#[st=new org.saml.SamlToken();st.field1=message.inboundProperties.field1; ... ; st]" />
in the when right before flow-ref.
PS. You can use #[message.inboundProperties.clientType] instead of #[message.inboundProperties['http.query.params']['clientType']]

java.io.IOException: Error writing request body to server

I am developing a web service to allow uploading from client to server. I was able to get wsdl file at http://localhost:9999/UploadWebservice?wsdl. Here is its content
<?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.1.6 in JDK 6. -->
<!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6. -->
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://ws/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ws/" name="ImageServerImplService">
<types></types>
<message name="upload">
<part name="arg0" type="xsd:string"></part>
<part name="arg1" type="xsd:base64Binary"></part>
</message>
<message name="uploadResponse">
<part name="return" type="xsd:string"></part>
</message>
<portType name="ImageServer">
<operation name="upload" parameterOrder="arg0 arg1">
<input message="tns:upload"></input>
<output message="tns:uploadResponse"></output>
</operation>
</portType>
<binding name="ImageServerImplPortBinding" type="tns:ImageServer">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"></soap:binding>
<operation name="upload">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal" namespace="http://ws/"></soap:body>
</input>
<output>
<soap:body use="literal" namespace="http://ws/"></soap:body>
</output>
</operation>
</binding>
<service name="ImageServerImplService">
<port name="ImageServerImplPort" binding="tns:ImageServerImplPortBinding">
<soap:address location="http://localhost:9999/UploadWebservice"></soap:address>
</port>
</service>
</definitions>
Now I am writing a client to consume the service. Here is the client
package ws;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Map;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.soap.SOAPBinding;
import com.sun.xml.ws.developer.JAXWSProperties;
public class ClientTaiwan {
public static void main(String[] args) {
ImageServerImplService service = new ImageServerImplService();
ImageServer delegate = service.getImageServerImplPort();
// Enable MTOM
BindingProvider bp = (BindingProvider) delegate;
SOAPBinding binding = (SOAPBinding) bp.getBinding();
binding.setMTOMEnabled(true);
// Set chunk size
Map<String, Object> ctxt =
((BindingProvider)delegate).getRequestContext();
ctxt.put(JAXWSProperties.HTTP_CLIENT_STREAMING_CHUNK_SIZE, 8192);
byte[] b;
try {
RandomAccessFile f = new RandomAccessFile("c:\\100MB.zip", "r");
b = new byte[(int) f.length()];
f.read(b);
f.close();
delegate.upload("c://Upload//100MB.zip", b);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Done!");
}
}
I receive the following stack trace
Exception in thread "main" javax.xml.ws.WebServiceException: java.io.IOException: Error writing request body to server
at com.sun.xml.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:225)
at com.sun.xml.ws.transport.http.client.HttpTransportPipe.processRequest(HttpTransportPipe.java:136)
at com.sun.xml.ws.transport.DeferredTransportPipe.processRequest(DeferredTransportPipe.java:110)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:1063)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:979)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:950)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:825)
at com.sun.xml.ws.client.Stub.process(Stub.java:443)
at com.sun.xml.ws.client.sei.SEIStub.doProcess(SEIStub.java:174)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:119)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:102)
at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:154)
at com.sun.proxy.$Proxy33.upload(Unknown Source)
at ws.ClientTaiwan.main(ClientTaiwan.java:47)
Caused by: java.io.IOException: Error writing request body to server
at sun.net.www.protocol.http.HttpURLConnection$StreamingOutputStream.checkError(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection$StreamingOutputStream.write(Unknown Source)
at com.sun.xml.ws.transport.http.client.HttpClientTransport$WSChunkedOuputStream.write(HttpClientTransport.java:365)
at javax.activation.DataHandler.writeTo(Unknown Source)
at com.sun.xml.ws.encoding.MtomCodec$ByteArrayBuffer.write(MtomCodec.java:229)
at com.sun.xml.ws.encoding.MtomCodec.encode(MtomCodec.java:185)
at com.sun.xml.ws.encoding.SOAPBindingCodec.encode(SOAPBindingCodec.java:242)
at com.sun.xml.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:214)
The line that causes the problem is delegate.upload("c://Upload//100MB.zip", b);
Why does a published service is still not visible for its client? How can I fix it?
If you have any concern about my coding style please let me know. Things are a little out of my control right now.
Best regards

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/

WSDL Client Generation not complete?

Just tried to generate java client generation from a WSDL file ( using XFire using XMLBeans binding )
I am able to generate the client + Fault Message ( no error ) , however input message and output message was not generated, it's also not generating the operation in the client. Is there anything wrong with my WSDL file, or is there anything I miss ?
Update :
I updated my test XFire project here.
I begin to suspect that the problem can be isoldated to the WSDL (because I can generate other WSDL successfully). I found these warnings, which I feel related :
WS-I: (BP2402) The wsdl:binding element does not use a
soapbind:binding element as defined in section "3 SOAP Binding." of
the WSDL 1.1 specification.
WS-I: (BP2032) Defective soapbind:fault element: the "name" attribute value does not match the value of the "name" attribute on
the parent element wsdl:fault.
WS-I: (AP2901) A description uses neither the WSDL MIME Binding as described in WSDL 1.1 Section 5 nor WSDL SOAP binding as described in
WSDL 1.1 Section 3 on each of the wsdl:input or wsdl:output elements
of a wsdl:binding.
Just found that soap12 might caused the issue. If I changed the xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/" to xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" and removing soapActionRequired in soap:operation it can generated the client successfully. But the webservice is currently only in soap1.2 only. So changing the wsdl to use soap1.1 is not the case here.
Here is my WSDL file :
<!--Created by TIBCO WSDL-->
<wsdl:definitions xmlns:tns="http://schemas.ocbc.com/soa/WSDL/service/CBS-CustAccountInfo-I" xmlns:soap1="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:jndi="http://www.tibco.com/namespaces/ws/2004/soap/apis/jndi" xmlns:ns="http://schemas.ocbc.com/soa/emf/common/envelope/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:jms="http://www.tibco.com/namespaces/ws/2004/soap/binding/JMS" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" name="Untitled" targetNamespace="http://schemas.ocbc.com/soa/WSDL/service/CBS-CustAccountInfo-I">
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://schemas.ocbc.com/soa/emf/common/envelope/" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:include schemaLocation="../Schemas/XML/CBS-CustAccountInfo-I-ServiceEnvelope.xsd"/>
</xs:schema>
</wsdl:types>
<wsdl:service name="CBS-CustAccountInfo-I">
<wsdl:port name="CBS-CustAccountInfo-I_HTTP" binding="tns:CBS-CustAccountInfo-I_HTTPBinding">
<soap:address location="https://localhost:15038/Services/CBS-CustAccountInfo-I/Processes/MainRequestResponse_HTTP"/>
</wsdl:port>
</wsdl:service>
<wsdl:portType name="PortType">
<wsdl:operation name="CBS-CustAccountInfo-I">
<wsdl:input message="tns:InputMessage"/>
<wsdl:output message="tns:OutputMessage"/>
<wsdl:fault name="fault1" message="tns:FaultMessage"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="CBS-CustAccountInfo-I_HTTPBinding" type="tns:PortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="CBS-CustAccountInfo-I">
<soap:operation style="document" soapAction="/Services/CBS-CustAccountInfo-I/Processes/MainRequestResponse_HTTP" soapActionRequired="true"/>
<wsdl:input>
<soap:body use="literal" parts="InputMessage"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal" parts="OutputMessage"/>
</wsdl:output>
<wsdl:fault name="fault1">
<soap:fault use="literal" name="fault1"/>
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
<wsdl:message name="InputMessage">
<wsdl:part name="InputMessage" element="ns:ServiceEnvelope"/>
</wsdl:message>
<wsdl:message name="OutputMessage">
<wsdl:part name="OutputMessage" element="ns:ServiceEnvelope"/>
</wsdl:message>
<wsdl:message name="FaultMessage">
<wsdl:part name="FaultMessage" element="ns:ServiceEnvelope"/>
</wsdl:message>
</wsdl:definitions>
And here is my ant task to generate :
<!-- Generating XML Beans -->
<target name="gen-xmlbeans">
<java classname="org.apache.xmlbeans.impl.tool.SchemaCompiler"
classpathref="build.classpath"
fork="true">
<arg value="-out"/>
<arg value="${basedir}/lib/ocbc.jar"/>
<arg value="${schema.path}"/>
</java>
</target>
<!-- Generating Client -->
<target name="ws-generate">
<taskdef name="wsgen" classname="org.codehaus.xfire.gen.WsGenTask">
<classpath>
<fileset dir="${lib.dir}" includes="*.jar" />
</classpath>
</taskdef>
<wsgen outputDirectory="${basedir}/src/" wsdl="${wsdl.path}" package="test.client" overwrite="true" binding="xmlbeans"/>
</target>
Generated Client :
public class CBS_CustAccountInfo_IClient {
private static XFireProxyFactory proxyFactory = new XFireProxyFactory();
private HashMap endpoints = new HashMap();
public CBS_CustAccountInfo_IClient() {
}
public Object getEndpoint(Endpoint endpoint) {
try {
return proxyFactory.create((endpoint).getBinding(), (endpoint).getUrl());
} catch (MalformedURLException e) {
throw new XFireRuntimeException("Invalid URL", e);
}
}
public Object getEndpoint(QName name) {
Endpoint endpoint = ((Endpoint) endpoints.get((name)));
if ((endpoint) == null) {
throw new IllegalStateException("No such endpoint!");
}
return getEndpoint((endpoint));
}
public Collection getEndpoints() {
return endpoints.values();
}
}
#Rudy If you have to use XFire, you might consider to try other binding such as JAXB binding and see if you're able to get the code generated properly.