Reputation: 1352
Our team is sending requests via soapUI to a remote service and collecting the responses. To automate this process, I made a simple java application being guided by the following tutorial.
http://drumcoder.co.uk/blog/2011/oct/18/httpclient-client-side-certificates/
The code is below.
Background:
Currently, we are using soapUI to send and receive messages. We specify a keystore for the requests and have to apply the outgoing WSS before sending. Once a response is received, we are manually copying and pasting it to a txt file. This gets very tedious and time consuming when there are hundreds of requests to process, so we are making a simple java application to run all of the requests and save off the corresponding responses. We used the above tutorial but it isn't working.
What is Working?
We currently save a SOAP request to a xml file manually, and then load, parse, and send the message to the service successfully using a java application. The response is also received and parsed successfully.
The Problem
The response received indicates a 500 internal server error, which is unexpected. Specifically, the custom error response indicates the service can not be found. I do recognize that a 500 internal server error is a pretty general problem and hard to debug without logs, though I do have some guesses.
Guesses to What is Wrong
One guess is that the endpoint / soap action is incorrect and the service cannot be found. I feel this is doubtful since we are using the exact credentials from the WSDL / soapUI.
Guess two is that SSL security is not being handled correctly and this is causing an internal server error during the server's authentication process. This is what I believe is the problem though I am unsure.
In General . . .
does anyone see the problem? Or if anything needs to be removed / added? Do you know of any other guides that may work better than this one for sending SOAP requests (I have tried java's javax.xml.soap API and that didn't work either, but resulted in the same error)? I have tried generating code from soapUI though I don't exactly know what to do with the resulting code (besides building with ant). I used http://java.dzone.com/tips/generating-client-java-code to generate the code though I don't know if it is what I am looking for.
Notes
We are calling a remote service that we do not have access to the logs.
The header in the SOAP request from the xml file is blank, unlike in soapUI where a security header is generated for the request when you apply an outgoing WSS. The bodies of the messages are equivalent. Even when the xml file containing the SOAP request loaded by the java application contains a non-expired security header (copied from soapUI after applying the outgoing WSS), the same invalid response is received.
When we copy the generated soapUI message from java (with non-expired security header) to soapUI, a valid response is received.
We do not have (and I suppose don't need) a truststore.
Can anyone see what may be going wrong? Is there any more information that would help solve the problem (minus logs)?
Thank You!
Code : (paths, passwords, and urls are general)
public class SOAPController {
static {
org.apache.xml.security.Init.init();
}
final static String KEY_STORE_PATH = "PATH";
final static String KEY_STORE_PASSWORD = "PASSWORD";
public static void main(String[] args) throws Exception {
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream keystoreInput = new FileInputStream(KEY_STORE_PATH);
keystore.load(keystoreInput, KEY_STORE_PASSWORD.toCharArray());
System.out.println("Keystore has " + keystore.size() + " keys");
SchemeRegistry schemeRegistry = new SchemeRegistry();
SSLSocketFactory lSchemeSocketFactory = new SSLSocketFactory(keystore, KEY_STORE_PASSWORD);
schemeRegistry.register(new Scheme("https", 443, lSchemeSocketFactory));
final HttpParams httpParams = new BasicHttpParams();
DefaultHttpClient lHttpClient = new DefaultHttpClient(new SingleClientConnManager(schemeRegistry), httpParams);
String lUrl = "URL";
String lXml = getStringFromDocument(new File("request1.xml"));
System.out.println(lXml + "\n\n\n");
HttpPost lMethod = new HttpPost(lUrl);
HttpEntity lEntity = new StringEntity(lXml, "text/xml", "UTF-8");
lMethod.setEntity(lEntity);
lMethod.setHeader("SOAPAction", "soapaction");
HttpResponse lHttpResponse = lHttpClient.execute(lMethod);
System.out.println("Response status code: "
+ lHttpResponse.getStatusLine().getStatusCode());
System.out.println("Response body: ");
System.out.println(EntityUtils.toString(lHttpResponse.getEntity()));
}
public static String getStringFromDocument(File file)
{
try
{
DocumentBuilderFactory dbFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(file);
DOMSource domSource = new DOMSource(doc);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(domSource, result);
return writer.toString();
}
catch(Exception ex)
{
ex.printStackTrace();
return null;
}
}
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.soap</groupId>
<artifactId>soap-util</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>soap-util</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient-cache</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.santuario</groupId>
<artifactId>xmlsec</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom2</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>javax.xml.soap</groupId>
<artifactId>javax.xml.soap-api</artifactId>
<version>1.3.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
</plugins>
</build>
Example SOAP Request (note empty header element):
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header/>
<soap:Body>
... same as soapUI request ...
</soap:Body>
</soap:Envelope>
Upvotes: 1
Views: 2893
Reputation: 1352
SOLVED:
So I left out a lot of header data. What made me realize this was when I looked at the raw request in soapUI, it had many headers that I did not have. I just added the following:
lMethod.addHeader(headerName1, headerValue1);
lMethod.addHeader(headerName2, headerValue2);
....
Upvotes: 2