Reputation: 4712
I have to call a secure WCF service from java using mutual authentication. Everything works fine except I'm unable to send messages which are greater than 48680 bytes in size. So 48680 byte messages are sent successfully, but 48681 byte - are not, and java application fails with read timed out exception, although WCF's quota settings permit much larger messages.
So what could be the problem?
EDIT
The source code:
package foo.bar;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
import javax.net.ssl.*;
import java.io.*;
import java.net.URL;
import java.security.KeyStore;
public class ReadTimedOutTest {
@Test
public void testReadTimedOut() throws Exception {
URL url = new URL("https://services/endpoint/");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
setUpSSL(connection);
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("SOAPAction", "http://namespace/2012/01/service/Operation");
connection.setRequestProperty("Accept", "*/*");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
connection.setConnectTimeout(10 * 1000);
connection.setReadTimeout(10 * 1000);
connection.setInstanceFollowRedirects(true);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
InputStream is = ReadTimedOutTest.class.getResourceAsStream("payload.failure.xml");
try {
IOUtils.copy(is, bos);
} finally {
is.close();
}
byte[] bytes = bos.toByteArray();
connection.setRequestProperty("Content-Length", String.valueOf(bytes.length));
OutputStream os = connection.getOutputStream();
try {
IOUtils.copy(new ByteArrayInputStream(bytes), os);
os.flush();
} finally {
os.close();
}
int respCode = connection.getResponseCode();
if(respCode >= HttpsURLConnection.HTTP_INTERNAL_ERROR) {
is = connection.getErrorStream();
try {
IOUtils.copy(is, System.err);
} finally {
is.close();
}
} else {
is = connection.getInputStream();
try {
IOUtils.copy(is, System.out);
} finally {
is.close();
}
}
}
private void setUpSSL(HttpsURLConnection connection) throws Exception {
byte[] bytes = FileUtils.readFileToByteArray(new File("d:\\workspace\\temp\\keystore"));
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new ByteArrayInputStream(bytes), "changeit".toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509");
keyManagerFactory.init(keyStore, "changeit".toCharArray());
bytes = FileUtils.readFileToByteArray(new File("d:\\workspace\\temp\\truststore"));
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new ByteArrayInputStream(bytes), "changeit".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
trustManagerFactory.init(trustStore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
SSLSocketFactory socketFactory = context.getSocketFactory();
connection.setSSLSocketFactory(socketFactory);
}
}
UPDATE
I have tested the service with .net WCF client and it was able to invoke the service successfully, so I'm wondering what could be the problem? Why WCF client is able to invoke the service and Java client, even if using ordinary HTTP POST request with UrlConnection, is not?
UPDATE
Here is sample of soap message
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<DoSomethingUseful xmlns="http://namespace/2012/01/service">
...
</DoSomethingUseful>
</soap:Body>
</soap:Envelope>
UPDATE
I was told that on the .net service side there are "Client certificate is required. No certificate was found in the request" messages which seem to occur on ssl session resumption. It happens only when Content-Length is greater than 48680 bytes. Also WCF service is configured with basicHttpBinding to use transport level security.
Upvotes: 6
Views: 1388
Reputation: 4712
Finally, I resolved the issue. The problem was the following:
Upvotes: 1
Reputation: 65391
This could be a SOAP version mismatch. The default version for basichttpbinding is SOAP 1.1. If the java client is using SOAP 1.2 you will get an error.
We have often seen that the error you get when the SOAP version does not match, has nothing to do with the real erros.
Upvotes: 0
Reputation: 7876
Have you tried sending in request from SOAPUI tool and checking if it behaves the same way. Also worth looking at the below link that discusses something about WCF Services and Java client.
Upvotes: 0
Reputation: 3671
You asked, what could be the problem, here some suggestion:
I would suggest to try a wider range of request. Do not only vary the size.
Upvotes: 0
Reputation: 1080
Have your tried to look at the actual packets being sent - eg. with tcpdump/Wireshark ( http://www.wireshark.org/ ) ?
I once had problems only on certain platforms reaching a service that was behind a very picky SSL offload engine.
Upvotes: 1