I have a flow with a custon filter that works(with an echo) but if I try tu use a twitter cloud connector i get this error
ERROR 2015-04-04 19:09:02,451 [[CopyTrabajosd2].trabajosdFlow.stage1.02] org.mule.retry.notifiers.ConnectNotifier: Failed to connect/reconnect: Work Descriptor. Root Exception was: Response code 403 mapped as failure. Message payload is of type: BufferInputStream. Type: class org.mule.module.http.internal.request.ResponseValidatorException
ERROR 2015-04-04 19:09:02,458 [[CopyTrabajosd2].trabajosdFlow.stage1.02] org.mule.exception.CatchMessagingExceptionStrategy:
********************************************************************************
Message : Response code 403 mapped as failure. Message payload is of type: BufferInputStream
Code : MULE_ERROR--2
--------------------------------------------------------------------------------
Exception stack is:
1. Response code 403 mapped as failure. Message payload is of type: BufferInputStream (org.mule.module.http.internal.request.ResponseValidatorException)
org.mule.module.http.internal.request.SuccessStatusCodeValidator:37 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/module/http/internal/request/ResponseValidatorException.html)
--------------------------------------------------------------------------------
Root Exception stack trace:
org.mule.module.http.internal.request.ResponseValidatorException: Response code 403 mapped as failure. Message payload is of type: BufferInputStream
at org.mule.module.http.internal.request.SuccessStatusCodeValidator.validate(SuccessStatusCodeValidator.java:37)
at org.mule.module.http.internal.request.DefaultHttpRequester.innerProcess(DefaultHttpRequester.java:202)
at org.mule.module.http.internal.request.DefaultHttpRequester.process(DefaultHttpRequester.java:166)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************
I think that the clout connector is not receiving the input type that it needs but I'm not sure ,any help?
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:twitter="http://www.mulesoft.org/schema/mule/twitter" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:json="http://www.mulesoft.org/schema/mule/json" xmlns:smtp="http://www.mulesoft.org/schema/mule/smtp"
xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" version="EE-3.6.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/smtp http://www.mulesoft.org/schema/mule/smtp/current/mule-smtp.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
http://www.mulesoft.org/schema/mule/twitter http://www.mulesoft.org/schema/mule/twitter/current/mule-twitter.xsd">
<smtp:gmail-connector name="gmail" doc:name="Gmail"/>
<http:request-config name="HTTP_Request_Configuration" host="api.openweathermap.org" port="80" basePath="data/2.5/forecast/daily?q=San Fernando,es&lang=es&units=metric&cnt=2&mode=json" doc:name="HTTP Request Configuration"/>
<spring:beans>
<spring:bean id="transformador" name="Bean" class="com.trabajosd.Transformador"/>
</spring:beans>
<twitter:config name="Twitter__Configuration" accessKey="3006010565-rUz6h4xnNoHO2juxGYQEK5jcM5DvSpxv7P3hv07" accessSecret="KxcqDQEo6JbHHR2S10lFN5luxXLEJauNhiBdZIeY7tUXO" consumerKey="LBxBQUYhbAFb5PeBtR7Jg4Evo" consumerSecret="AdD8lJYRS1OadJsn2BXhEbnhdcUNc1t3uM9pnOGH7eNfE2JxZu" doc:name="Twitter: Configuration"/>
<flow name="trabajosdFlow">
<poll doc:name="Poll">
<fixed-frequency-scheduler frequency="10000"/>
<http:request config-ref="HTTP_Request_Configuration" path="/" method="GET" doc:name="HTTP"/>
</poll>
<logger level="INFO" doc:name="Logger"/>
<byte-array-to-string-transformer doc:name="Byte Array to String"/>
<json:json-to-object-transformer doc:name="JSON to Object"/>
<custom-filter class="com.trabajosd.Filtro" doc:name="Custom"/>
<twitter:update-status config-ref="Twitter__Configuration" status="Predicción de lluvia para hoy(Prueba Mule)" doc:name="Twitter"/>
<catch-exception-strategy doc:name="Catch Exception Strategy"/>
</flow>
<catch-exception-strategy name="trabajosdCatch_Exception_Strategy">
<logger level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
</mule>
And the custon filter class
package com.trabajosd;
import org.json.JSONArray;
import org.json.JSONObject;
import org.mule.api.MuleMessage;
import org.mule.api.routing.filter.Filter;
public class Filtro implements Filter{
#Override
public boolean accept(MuleMessage message) {
try {
String json=message.getPayloadAsString();
JSONObject obj = new JSONObject(json);
JSONArray lista = obj.getJSONArray("list");
JSONObject elemento0 =lista.getJSONObject(0);
JSONArray clima = elemento0.getJSONArray("weather");
JSONObject prediccion = clima.getJSONObject(0);
return prediccion.getString("main").equalsIgnoreCase("Clouds");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
}
It seems that there is an issue with WWW-authenticate header header in Mule 3.6.x.
The error usually is "401 response received, but no WWW-Authenticate header was present". Not sure why it is http response 403 in your case.
I tried a basic twitter flow and it works on Mule 3.5 but not 3.6.
The reported issues are:
https://www.mulesoft.org/jira/browse/MULE-8282
https://www.mulesoft.org/jira/browse/MULE-8127
https://www.mulesoft.org/jira/browse/MULE-8249
Related
I am using a channel adaptor and qmux to send iso8583 message to a socket server.
I write 2 maven project Jpos client & server in netbeans.
The server accepts the connection but doesnt receive the message (or the client doesnt send message) but when I cancel process of the client project, the server receives
Plz correct me if i wrong.
Following are my configuration files (Refered to http://jpos.org/doc/proguide-draft.pdf)
10_channel.xml
<?xml version="1.0" encoding="UTF-8"?>
<channel-adaptor name='test-channel'
class="org.jpos.q2.iso.ChannelAdaptor" logger="Q2">
<channel class="org.jpos.iso.channel.ASCIIChannel" logger="Q2" realm="test-channel"
packager="org.jpos.iso.packager.GenericPackager">
<property name="packager-config" value="src/main/resources/iso8583.xml" />
<property name="host" value="127.0.0.1" />
<property name="port" value="9090" />
<property name="connection-timeout" value="15000" />
<property name="timeout" value="3000000" />
<property name="keep-alive" value="true" />
</channel>
<!-- <ignore-iso-exceptions>yes</ignore-iso-exceptions>-->
<in>client-send</in>
<out>client-receive</out>
<reconnect-delay>10000</reconnect-delay>
</channel-adaptor>
20_mux.xml
<?xml version="1.0" encoding="UTF-8"?>
<mux class="org.jpos.q2.iso.QMUX" logger="Q2" name="test-mux">
<in>client-receive</in>
<out>client-send</out>
<ready>test-channel.ready</ready>
<unhandled>myunhandledqueue</unhandled>
<key>2 7</key>
</mux>
JPos Client code
Q2 q2 = new Q2("src/main/deploy/");
q2.start();
QMUX mux = (QMUX)NameRegistrar.getIfExists("mux.test-mux");
if (mux != null && mux.isConnected()) {
ISOMsg request = new IsoMessage().build(); //dump iso message
ISOMsg response = mux.request(request, REQUEST_TIMEOUT);
if (response != null) {
ISOMsg receivedIsoMsg = new ISOMsg();
receivedIsoMsg.setPackager(new GenericPackager("path_to_file_xml"));
receivedIsoMsg.unpack(response.getBytes());
receivedIsoMsg.dump(System.out, "");
}
}
Socket Server Code
ServerSocket serverSocket;
try {
System.out.println("Binding to port " + SERVER_PORT + ", please wait ...");
serverSocket = new ServerSocket(SERVER_PORT);
System.out.println("Server started: " + serverSocket);
System.out.println("Waiting for a client ...");
while (true) {
try {
Socket socket = serverSocket.accept();
DataInputStream dis = new DataInputStream(socket.getInputStream());
String message = (String) dis.readLine();
System.out.println("Message Received: " + message);
ISOMsg receivedIsoMsg = new ISOMsg();
receivedIsoMsg.setPackager(new GenericPackager("path_to_file_xml"));
receivedIsoMsg.unpack(message.getBytes());
receivedIsoMsg.setMTI("0110");
receivedIsoMsg.set(39,"00");
receivedIsoMsg.dump(System.out, "");
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
//write object to Socket
dos.writeUTF(new String(receivedIsoMsg.pack()));
} catch (IOException | ISOException ex) {
System.err.println(ex);
}
}
} catch (IOException e1) {
try {
serverSocket.close();
} catch (IOException ex) {
System.err.println(ex);
}
}
Trace log
Client:
--- exec-maven-plugin:1.2.1:exec (default-cli) # JposTest ---
<log realm="Q2.system" at="2020-07-30T10:45:25.638">
<info>
Q2 started, deployDir=/Users/lap/NetBeansProjects/JposTest/src/main/deploy, environment=default
</info>
</log>
<log realm="Q2.system" at="2020-07-30T10:45:26.160" lifespan="507ms">
<version>
jPOS 2.1.3 master/95b8dce (2019-06-16 15:16:57 ART)
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
jPOS Community Edition, licensed under GNU AGPL v3.0.
This software is probably not suitable for commercial use.
Please see http://jpos.org/license for details.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Darwin)
iQEcBAEBAgAGBQJMolHDAAoJEOQyeO71nYtFv74H/3OgehDGEy1VXp2U3/GcAobg
HH2eZjPUz53r38ARPiU3pzm9LwDa3WZgJJaa/b9VrJwKvbPwe9+0kY3gScDE1skT
ladHt+KHHmGQArEutkzHlpZa73RbroFEIa1qmN6MaDEHGoxZqDh0Sv2cpvOaVYGO
St8ZaddLBPC17bSjAPWo9sWbvL7FgPFOHhnPmbeux8SLtnfWxXWsgo5hLBanKmO1
1z+I/w/6DL6ZYZU6bAJUk+eyVVImJqw0x3IEElI07Nh9MC6BA4iJ77ejobj8HI2r
q9ulRPEqH9NR79619lNKVUkE206dVlXo7xHmJS1QZy5v/GT66xBxyDVfTduPFXk=
=oP+v
-----END PGP SIGNATURE-----
</version>
</log>
<log realm="Q2.system" at="2020-07-30T10:45:26.168" lifespan="5ms">
<info>
deploy: /Users/lap/NetBeansProjects/JposTest/src/main/deploy/10_zp_channel.xml
</info>
</log>
<log realm="Q2.system" at="2020-07-30T10:45:26.199" lifespan="30ms">
<info>
deploy: /Users/lap/NetBeansProjects/JposTest/src/main/deploy/20_zp_qmux.xml
</info>
</log>
<log realm="Q2.system" at="2020-07-30T10:45:26.207" lifespan="8ms">
<info>
deploy: /Users/lap/NetBeansProjects/JposTest/src/main/deploy/99_sysmon.xml
</info>
</log>
<log realm="org.jpos.q2.qbean.SystemMonitor" at="2020-07-30T10:45:26.225">
<info>
Starting SystemMonitor
</info>
</log>
<log realm="org.jpos.q2.qbean.SystemMonitor" at="2020-07-30T10:45:26.225">
<info>
......
thread count: 10
peak threads: 10
user threads: 7
Thread[Reference Handler,10,system]
Thread[Finalizer,8,system]
Thread[Signal Dispatcher,9,system]
Thread[main,5,main]
Thread[pool-1-thread-1,5,main]
Thread[Q2-dd666708-34a1-46dc-9a10-4df253d9249a,5,main]
Thread[Thread-1,5,main]
Thread[channel-sender-client-send,5,main]
Thread[channel-receiver-client-receive,5,main]
Thread[SystemMonitor,5,main]
name-registrar:
tspace:default: org.jpos.space.TSpace
key-count: 0
gcinfo: 0,0
Q2: org.jpos.q2.Q2
test-channel: org.jpos.q2.iso.ChannelAdaptor
tx=0, rx=0, connects=0, last=0
logger.Q2: org.jpos.util.Logger
channel.test-channel: org.jpos.iso.channel.ASCIIChannel
mux.test-mux: org.jpos.q2.iso.QMUX
tx=0, rx=0, tx_expired=0, tx_pending=0, rx_expired=0, rx_pending=0, rx_unhandled=0, rx_forwarded=0, connected=false, last=0
logger.: org.jpos.util.Logger
</info>
</log>
<log realm="test-channel/127.0.0.1:9090" at="2020-07-30T10:45:36.309" lifespan="10084ms">
<connect>
Try 0 127.0.0.1:9090
</connect>
</log>
<log realm="test-channel/127.0.0.1:9090" at="2020-07-30T10:45:55.579" lifespan="1ms">
<send>
<isomsg direction="outgoing">
<!-- org.jpos.iso.packager.GenericPackager[src/main/resources/iso8583.xml] -->
<field id="0" value="0100"/>
<field id="2" value="123456"/>
<field id="3" value="000010"/>
<field id="4" value="1500"/>
<field id="7" value="1206041200"/>
<field id="11" value="000001"/>
<field id="41" value="12340001"/>
<field id="49" value="840"/>
</isomsg>
</send>
</log>
Server:
--- exec-maven-plugin:1.2.1:exec (default-cli) # AppTest ---
Binding to port 9090, please wait ...
Server started: ServerSocket[addr=0.0.0.0/0.0.0.0,localport=9090]
Waiting for a client ...
Client accepted: Socket[addr=/127.0.0.1,port=58902,localport=9090]
=> the Client cannot send message
But if I cancel process of client project, the Server receives message & print log:
Message Received: 00730100722000000080800006123456000010000000001500120604120000000112340001840
<isomsg>
<!-- org.jpos.iso.packager.GenericPackager -->
<field id="0" value="0110"/>
<field id="8" value="80000612"/>
<field id="18" value="3456"/>
<field id="19" value="000"/>
<field id="20" value="010"/>
<field id="23" value="000"/>
<field id="27" value="0"/>
<field id="39" value="00"/>
<field id="57" value=""/>
</isomsg>
Problem is you are trying to receive the message using readLine and iso messages are not strings ended with an EOL.
I believe what's happening is that when the client disconnects the readLine method returns, because the input stream is closed.
It would be better to use ISOServer on your server, or even better a full q2 to implement it.
Otherwise you should first read the message length and then read that amount of bytes from the input stream, instead of waiting for a new line character that may or may not be part of the message itself
You can follow the first two jpos tutorials here http://www.jpos.org/tutorials, to get an idea on how to configure a Server with a request listener to process requests.
I am trying to send message with:
netcat -u localhost 11111abcd
I just need that the client get answer: OK It get the message and try to answer with OK.
But it writes this infinitely to application log:
Message: GenericMessage [payload=byte[2], headers={ip_packetAddress=127.0.0.1/127.0.0.1:49489, ip_address=127.0.0.1, id=8db6aa3b-b56b-6dce-9554-c7b0ce050142, ip_port=49489, ip_hostname=127.0.0.1, timestamp=1494442285767}]
Message Payload: OK
Config:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd">
<int:channel id="sendUdp"/>
<int-ip:udp-outbound-channel-adapter id="udpOut" host="localhost" port="11111"
multicast="false" check-length="false"
channel="sendUdp" />
<int-ip:udp-inbound-channel-adapter id="udpIn" port="11111" receive-buffer-size="500"
multicast="false" check-length="false"
channel="receiveUdp"/>
<int:service-activator id="updHandler" input-channel="receiveUdp" output-channel="sendUdp" ref="listener"/>
</beans>
#ServiceActivator
public String handle(Message<?> message) {
System.out.println("*** Message: " + message);
String command = new String((byte[]) message.getPayload());
System.out.println("*** Message Payload: "
+ command);
String response = "OK";
return response;
}
Your outbound adapter is sending messages to the inbound adapter. If you want to reply to a packet, you need to configure the socket and destination expressions. See the documentation.
<int-ip:udp-inbound-channel-adapter id="inbound" port="11111" channel="in" />
<int:channel id="in" />
<int:transformer expression="new String(payload).toUpperCase()"
input-channel="in" output-channel="out"/>
<int:channel id="out" />
<int-ip:udp-outbound-channel-adapter id="outbound"
socket-expression="#inbound.socket"
destination-expression="headers['ip_packetAddress']"
channel="out" />
I try to send the post request to API using ESB mule. Hence i have created flow like below.
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:json="http://www.mulesoft.org/schema/mule/json" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd">
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8110" doc:name="HTTP Listener Configuration"/>
<http:request-config name="HTTP_Request_Configuration" host="api.bonanza.com" port="443" doc:name="HTTP Request Configuration" protocol="HTTPS"/>
<flow name="bonanza_fetchtoken_ceFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/fetchtoken" allowedMethods="GET" doc:name="HTTP"/>
<message-properties-transformer doc:name="Message Properties">
<add-message-property key="X-BONANZLE-API-DEV-NAME" value="t**********I"/>
<add-message-property key="X-BONANZLE-API-CERT-NAME" value="l**********F"/>
</message-properties-transformer>
<set-payload value="fetchTokenRequest" doc:name="Set Payload"/>
<set-property propertyName="Content-Type" value="text/plain" doc:name="Property"/>
<set-property propertyName="Accept" value="application/json" doc:name="Property"/>
<http:request config-ref="HTTP_Request_Configuration" path="/api_requests/secure_request" method="POST" doc:name="HTTP" followRedirects="true" parseResponse="false">
<http:success-status-code-validator values="0..599"/>
</http:request>
</flow>
</mule>
In the API documentation, they have provided the sample code for java to send and receive response and it is working in my local too. The java code snippet is below.
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.HttpURLConnection;
public class FetchToken {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
String devId = "t******I";
String certId = "l*******F";
URL url = new URL("https://api.bonanza.com/api_requests/secure_request");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("X-BONANZLE-API-DEV-NAME", devId);
connection.setRequestProperty("X-BONANZLE-API-CERT-NAME", certId);
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
String requestName = "fetchTokenRequest";
writer.write(requestName);
writer.flush();
writer.close();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String response = in.readLine();
JSONObject jsonResponse = new JSONObject(response);
if (jsonResponse.optString("ack").equals("Success")
&& jsonResponse.optJSONObject("fetchTokenResponse") != null) {
// Success! Now read more keys from the json object
JSONObject fetchTokenJson = jsonResponse.optJSONObject("fetchTokenResponse");
System.out.println("Your token: " + fetchTokenJson.optString("authToken"));
System.out.println("Token expiration time: " + fetchTokenJson.optString("hardExpirationTime"));
System.out.println("Authentication URL: " + fetchTokenJson.optString("authenticationURL"));
}
} catch (Exception e) {
System.out.println(e);
}
}
}
The above java program retuning token without issue. When i use my esb mule i am getting below API error. What are the mistakes i doing while building request. How can i get successful response from API ?
{
"ack": "Failure",
"version": "1.0beta",
"timestamp": "2016-03-09T10:35:16.000Z",
"errorMessage": {
"message": "Cannot determine what type of request you are making. Often this can be the result of data that has not been escaped before being passed to the API. If you are passing data with quotation marks or other special characters, you should translate it to JSON, then escape it, before sending it over the API."
}
}
Solving your problem implies performing debugging steps. I'm going to walk you through them.
Hypothesis: Maybe the receiving service is confused by some extra headers sent by Mule?
Try the following:
Send the Mule request to http://requestb.in/ and look exactly how it is structured.
Then send the same request to api.bonanza.com from Java, it should fail too.
Remove extra stuff bit by bit until it works.
Then come back to Mule and ensure that it creates the same request by tuning the headers it sends, fixing any other differences...
I am having trouble getting WCF binding to work with Blackboard Java Web Services API.
(Simple answer would be if anyone has got this working could you
please post a working binding for WCF to Blackboard)
I have spent hours trying different configurations and custom coded bindings.
Some unsuccessful attempts:
calling-a-ws-security-java-web-service-with-c-sharp-client
wcf-client-with-ws-security 12-common-wcf-interop-confusions
configure-wcf-for-ws-security-with-username-over-https
wcf-client-connecting-to-java-soap-web-service-using-ws-security
ClearUsernameBinding
There are many more to do with JAVA and WS-Security with WCF but I wont go on.
It seems that every time I get one thing working another breaks. Now I feel like I am going around in circles and just making myself even more confused.
As my first test what I am trying to do is simple Initialize the Context object and Login using an Admin test user account with a WCF proxy.
Blackboard Doc ContextWS
To make sure that all of this worked I first I downloaded the sample code for .Net WSE 2.0 and tested that, it worked perfectly.
Now when I use WCF and binding I cannot get this same behaviour.
First the Successful exchange with very old WSE 2.0
===================================
WSE 2.0 ContextWS Initialization
<?xml version="1.0" encoding="utf-8"?>
<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" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soap:Header>
<wsa:Action>initialize</wsa:Action>
<wsa:MessageID>uuid:b975e989-a4ce-4e1e-abd6-500945346c40</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:To>https://Blackboard.Server.Name/webapps/ws/services/Context.WS</wsa:To>
<wsse:Security soap:mustUnderstand="1">
<wsu:Timestamp wsu:Id="Timestamp-47d0d017-4fd1-46c2-b1b4-2431402cf847">
<wsu:Created>2015-07-16T04:58:02Z</wsu:Created>
<wsu:Expires>2015-07-16T05:03:02Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-1b71e23a-2d84-40a5-9509-b75902ec8b76">
<wsse:Username>session</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">nosession</wsse:Password>
<wsse:Nonce>lAW2qXrXZ1maNNkCEzlHGA==</wsse:Nonce>
<wsu:Created>2015-07-16T04:58:02Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soap:Header>
<soap:Body />
</soap:Envelope>
WSE 2.0 ContextWS Initialization Success Response
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns:initializeResponse xmlns:ns="http://context.ws.blackboard">
<ns:return>c2762f357bbc42a4a88d33e4e42486b8</ns:return>
</ns:initializeResponse>
</soapenv:Body>
</soapenv:Envelope>
WSE 2.0 ContextWS Login Request
<?xml version="1.0" encoding="utf-8"?>
<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" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soap:Header>
<wsa:Action>login</wsa:Action>
<wsa:MessageID>uuid:a823128b-efb4-49e1-87d9-fd35167f0bfc</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:To>https://Blackboard.Server.Name/webapps/ws/services/Context.WS</wsa:To>
<wsse:Security soap:mustUnderstand="1">
<wsu:Timestamp wsu:Id="Timestamp-c38daf19-6b39-4391-a3f8-bcc030064a3e">
<wsu:Created>2015-07-16T04:58:15Z</wsu:Created>
<wsu:Expires>2015-07-16T05:03:15Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-65948746-e616-436a-85f4-d2e1023e39be">
<wsse:Username>session</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">c2762f357bbc42a4a88d33e4e42486b8</wsse:Password>
<wsse:Nonce>T0xs8aiaiODMK3sfKgDQtg==</wsse:Nonce>
<wsu:Created>2015-07-16T04:58:15Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soap:Header>
<soap:Body>
<login xmlns="http://context.ws.blackboard">
<userid>test_admin</userid>
<password>TestPassword</password>
<clientVendorId>TestClient</clientVendorId>
<clientProgramId>TestPOC</clientProgramId>
<loginExtraInfo xsi:nil="true" />
<expectedLifeSeconds>10000000</expectedLifeSeconds>
</login>
</soap:Body>
</soap:Envelope>
WSE 2.0 ContextWS Login Success Response
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns:loginResponse xmlns:ns="http://context.ws.blackboard">
<ns:return>true</ns:return>
</ns:loginResponse>
</soapenv:Body>
</soapenv:Envelope>
===================================
So I know that this works to our environment and I know the user can login.
Using WCF I am able to get the Initialization working but then it looses the session. It does not put the Returned Session ID into the Password field for the next message. I have tried to do this manually of course; but I get an error stating the Password field is read only.
Now for my WCF Configuration and code that has gotten me closest to the above communication.
WCF App.Config Binding
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
</system.serviceModel>
<bindings>
<customBinding>
<binding name="WCFSoapInteropJavaWS" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" >
<textMessageEncoding messageVersion="Soap11" writeEncoding="utf-8" />
<security authenticationMode="UserNameOverTransport" enableUnsecuredResponse="true" allowSerializedSigningTokenOnReply="true"
messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
includeTimestamp="true" allowInsecureTransport="true" canRenewSecurityContextToken="false" >
</security>
<httpsTransport authenticationScheme="Anonymous" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint
address="https://Blackboard.Server.Name:443/webapps/ws/services/Context.WS"
binding="customBinding" bindingConfiguration="WCFSoapInteropJavaWS"
contract="ContextWS.ContextWSPortType" name="Context.WCFSoapInteropJavaWS" />
</client>
</system.serviceModel>
</configuration>
WCF C# code
public bool testWrapper(String userId, String userPassword){
try
{
context = new ContextWrapper("Context.WCFSoapInteropJavaWS");
context.ClientCredentials.UserName.UserName = "session";
context.ClientCredentials.UserName.Password = "nosession";
context.initialize();
//context.ClientCredentials.UserName.Password = "886d935527944f94a3526288e39a555e"; // SessionGUID_HERE Throws a Read Only Error for Pasword
bool retval = context.login(userId, userPassword, vendorId, programId, null, expectedLife);
return retval;
}
catch (System.Exception e)
{
lastError = e;
return false;
}
}
This is what the SOAP communication looks like.
WCF ContextWS Initialization Request
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPo+FmveflwUtMgSATRu3Ht9EAAAAAmYVJsX+bhUeYcTDsFqFktkqe8xmMiA1MpXouaouXgJwACQAA</VsDebuggerCausalityData>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="_0">
<u:Created>2015-07-16T07:15:05.109Z</u:Created>
<u:Expires>2015-07-16T07:20:05.109Z</u:Expires>
</u:Timestamp>
<o:UsernameToken u:Id="uuid-1237f56c-7c68-4d40-a756-7ff2c19a3235-1">
<o:Username>session</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">nosession</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"/>
</s:Envelope>
WCF ContextWS Initialization Success Response
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns:initializeResponse xmlns:ns="http://context.ws.blackboard">
<ns:return>886d935527944f94a3526288e39a555e</ns:return>
</ns:initializeResponse>
</soapenv:Body>
</soapenv:Envelope>
WCF ContextWS Login Request
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPo+JmveflwUtMgSATRu3Ht9EAAAAAmYVJsX+bhUeYcTDsFqFktkqe8xmMiA1MpXouaouXgJwACQAA</VsDebuggerCausalityData>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="_0">
<u:Created>2015-07-16T07:15:14.033Z</u:Created>
<u:Expires>2015-07-16T07:20:14.033Z</u:Expires>
</u:Timestamp>
<o:UsernameToken u:Id="uuid-1237f56c-7c68-4d40-a756-7ff2c19a3235-1">
<o:Username>session</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">nosession</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<login xmlns="http://context.ws.blackboard">
<userid>Test_admin</userid>
<password>TestPassword</password>
<clientVendorId>TestClient</clientVendorId>
<clientProgramId>TestPOC</clientProgramId>
<loginExtraInfo xsi:nil="true"/>
<expectedLifeSeconds>10000000</expectedLifeSeconds>
</login>
</s:Body>
</s:Envelope>
WCF ContextWS Login Failed Response
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<soapenv:Fault>
<faultcode>soapenv:Server</faultcode>
<faultstring>[WSFW001]Invalid session</faultstring>
<detail />
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
As you can see the session return id has not been added to the password field on the login request so there is a "Invalid Session:
It all seemed to be going so well.
In short if anyone knows how to achieve a binding from a WCF Client to the Blackboard Java Webservice API and example would be fantastic. Other wise I am hoping that someone else that knows more about WCF Bindings to Java than I do might be able to take a look at the above see where I am going wrong.
Any help anyone can give me to get this working would be much appreciated so thanks. I really am hoping it is just something silly that I am missing.
Sorry for such a long detailed question.
Thanks to heaps of reading and some useful samples I was able to get this working. Blackboard with WCF.
Thanks go to both:
Ajadex Lopez
http://www.isyourcode.com/2010/08/attaching-oasis-username-tokens-headers.html
Johnny Lockhart
"Incoming message does not contain required Security header"
BB is buggie so you might do best to search the forum for WCF to find the post
Sample class
using System;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.ServiceModel;
using System.Xml;
using System.Security.Cryptography;
using System.Text;
namespace BBWcfWrapper
{
/// <summary>
/// Coupled with the additional classes below, allows for injecting the WS-Security header into a WCF Service call without requiring SSL on the server.
/// </summary>
/// <remarks>http://isyourcode.blogspot.com/2010/08/attaching-oasis-username-tokens-headers.html</remarks>
public class BBWSSecurityBehavior : IEndpointBehavior
{
public MessageInspector MessageInspector { get; set; }
public BBWSSecurityBehavior(MessageInspector messageInspector)
{
MessageInspector = messageInspector;
}
public void Validate(ServiceEndpoint endpoint)
{ }
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{ }
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
if (this.MessageInspector == null) throw new InvalidOperationException("Caller must supply ClientInspector.");
clientRuntime.MessageInspectors.Add(MessageInspector);
}
}
public class MessageInspector : IClientMessageInspector
{
public MessageHeader[] Headers { get; set; }
public MessageInspector(params MessageHeader[] headers)
{
Headers = headers;
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
if (Headers != null)
{
for (int i = Headers.Length - 1; i >= 0; i--)
{
request.Headers.Insert(0, Headers[i]);
}
}
return request;
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
}
public class SecurityHeader : MessageHeader
{
public string SystemUser { get; set; }
public string SystemPassword { get; set; }
public SecurityHeader(string systemUser, string systemPassword)
{
SystemUser = systemUser;
SystemPassword = systemPassword;
}
public override string Name
{
get { return "Security"; }
}
public override string Namespace
{
get { return "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; }
}
protected override void OnWriteStartHeader(XmlDictionaryWriter writer, MessageVersion messageVersion)
{
writer.WriteStartElement("wsse", Name, Namespace);
writer.WriteXmlnsAttribute("wsse", Namespace);
writer.WriteAttributeString("soap", "mustUnderstand", Namespace, "1");
}
protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
{
WriteHeader(writer);
}
private void WriteHeader(XmlDictionaryWriter writer)
{
var createDate = DateTime.Now;
//Start Parent Elements
writer.WriteStartElement("wsu","Timestamp","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
writer.WriteAttributeString("wsu","id","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd","Timestamp-6557466");
#region Start Child Elements
writer.WriteStartElement("wsu", "Created", XmlConvert.ToString(createDate, "yyyy-MM-ddTHH:mm:sszzzzzz"));
writer.WriteEndElement(); //End Created
writer.WriteStartElement("wsu", "Expires", XmlConvert.ToString(createDate.AddDays(1), "yyyy-MM-ddTHH:mm:sszzzzzz"));
writer.WriteEndElement(); //End Expires
#endregion
writer.WriteEndElement(); //End Timestamp
//Start Parent Elements
writer.WriteStartElement("wsse", "UsernameToken", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
writer.WriteXmlnsAttribute("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
#region Start Child Elements
writer.WriteStartElement("wsse", "Username", null);
writer.WriteString(SystemUser);
writer.WriteEndElement();//End Username
writer.WriteStartElement("wsse", "Password", null);
writer.WriteAttributeString("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
writer.WriteString(SystemPassword);
writer.WriteEndElement();//End Password
// unique Nonce value - encode with SHA-1 for 'randomness'
// in theory the nonce could just be the GUID by itself
// This is used to stop Replay attacks
writer.WriteStartElement("wsse", "Nonce", null);
writer.WriteString(GetSHA1String(Guid.NewGuid().ToString()));
writer.WriteEndElement();//Nonce
writer.WriteStartElement("wsu", "Created", null);
writer.WriteString(XmlConvert.ToString(createDate, "yyyy-MM-ddTHH:mm:sszzzzzz"));
writer.WriteEndElement(); //End Created
#endregion
writer.WriteEndElement();//End UsernameToken
writer.Flush();
}
protected string GetSHA1String(string phrase)
{
SHA1CryptoServiceProvider sha1Hasher = new SHA1CryptoServiceProvider();
byte[] hashedDataBytes = sha1Hasher.ComputeHash(Encoding.UTF8.GetBytes(phrase));
return Convert.ToBase64String(hashedDataBytes);
}
}
}
Example Use
calendar = new CalendarWrapper("Calendar.BB_WSSecurity_Binding");
//This adds a custom security Headder for WCF and Java WS-Security Interop
calendar.Endpoint.Behaviors.Add(new BBWSSecurityBehavior(new MessageInspector(BbWsAuth.SecurityHeader)));
calendar.initializeCalendarWS(false);
Simple Wrapper class
public class CalendarWrapper : CalendarWSPortTypeClient
{
public CalendarWrapper() : base() { }
public CalendarWrapper(string endpointConfigurationName) : base(endpointConfigurationName) { }
public CalendarWrapper(Binding binding, EndpointAddress remoteAddress) : base(binding, remoteAddress) { }
}
Config
<bindings>
<basicHttpsBinding>
<binding name="BB_WSSecurity_Binding" messageEncoding="Text" textEncoding="utf-8" maxReceivedMessageSize="4000000" >
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</binding>
</basicHttpsBinding>
</bindings>
<client>
<endpoint address="https://xxxxxxxxxx/webapps/ws/services/Calendar.WS"
binding="basicHttpsBinding" bindingConfiguration="BB_WSSecurity_Binding"
contract="CalendarWS.CalendarWSPortType" name="Calendar.BB_WSSecurity_Binding" />
I am using a schema-validation-filter inside a processor-chain on a flow, and i want to set a custom error-handler so that i can save the invalid lines of XML, but the problem is that my "schemaErrorHandler" is NEVER executed.
Note: My custom resource resolver, that is configured in a similar fashion as seen below, has no problems at all.
I already tried to wrap out the schema-validation-filter from the message-filter and to remove the throwOnUnaccepted="true" atribbute from it but the schemaErrorHandler is never executed.
This is a bug or I'm missing something? Neither found no JIRAs related to this .
xml
<processor-chain>
<message-filter onUnaccepted="TextValidator">
<mxml:is-xml-filter />
</message-filter>
<message-filter throwOnUnaccepted="true">
<mxml:schema-validation-filter errorHandler-ref="schemaErrorHandler" resourceResolver-ref="schemaResourceResolver" schemaLocations="mySchema.xsd"/>
</message-filter>
</processor-chain>
<spring:bean id="schemaResourceResolver" name="schemaResourceResolver" class="my.app.SchemaResourceResolver"/>
<spring:bean id="schemaErrorHandler" name="schemaErrorHandler" class="my.app.SchemaErrorHandler"/>
SchemaErrorHandler.java
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
public class SchemaErrorHandler implements ErrorHandler {
private List<Object> allErrors = new ArrayList<>();
public List<Object> getAllErrors() {
return allErrors;
}
public void setAllErrors(List<Object> allErrors) {
this.allErrors = allErrors;
}
#Override
public void error(SAXParseException arg0) throws SAXException {
System.out.println(arg0.getMessage());
allErrors.add(arg0);
}
#Override
public void fatalError(SAXParseException arg0) throws SAXException {
System.out.println(arg0.getMessage());
allErrors.add(arg0);
}
#Override
public void warning(SAXParseException arg0) throws SAXException {
System.out.println(arg0.getMessage());
allErrors.add(arg0);
}
}
for making the flow work you need to use a different approach. Attaching an example xml
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml"
xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:file="http://www.mulesoft.org/schema/mule/file"
xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" version="EE-3.4.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd
http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd">
<spring:beans>
<spring:bean id="schemaErrorHandler" name="schemaErrorHandler"
class="SchemaErrorHandler" />
</spring:beans>
<flow name="xml_schemaFlow1" doc:name="xml_schemaFlow1">
<file:inbound-endpoint path="/home/anil/deleteme/xsd/file"
responseTimeout="10000" doc:name="File" />
<message-filter name="asdf" onUnaccepted="invalidRelationXmlFlow"
doc:name="Message">
<mulexml:schema-validation-filter
schemaLocations="/home/anil/deleteme/xsd/xsd/abc.xsd"
errorHandler-ref="schemaErrorHandler" returnResult="true"
doc:name="Schema Validation">
</mulexml:schema-validation-filter>
</message-filter>
<echo-component doc:name="Echo" />
</flow>
<flow name="invalidRelationXmlFlow" doc:name="invalidRelationXmlFlow">
<logger level="INFO" doc:name="Logger" message="hello"/>
</flow>
This will give you a warning in mule but does work. fine.
In case of file validation failure the invalidRelationXmlFlow will get called.