When testing the Web Agent sample in Java, I am getting an error reply
<?xml version="1.0" encoding="utf-8"?>
<response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" type="error">
<Error>
<returnCode>706</returnCode>
<errorMessage>Value cannot be null.
Parameter name: s</errorMessage>
</Error>
</response>
I followed the Ruby example in the CoSign Web Agent samples and the documentation
I have used the demo.pdf file provided in the sample.
This is the XML (from test app) sent in the POST request (the <content></content>
has the Base64 encoded PDF, but omitted because of length).
<?xml version="1.0" encoding="utf-8" ?>
<request>
<Logic>
<allowAdHoc>true</allowAdHoc>
<workingMode>pull</workingMode>
<enforceReason>false</enforceReason>
</Logic>
<Url>
<finishURL>http://localhost:64956/retrieveSignedFile.aspx</finishURL>
</Url>
<Document>
<fileID>1234567890</fileID>
<contentType>pdf</contentType>
<content>{BASE64 encoded pdf content}</content>
</Document>
</request>
The following is the java code I have used:
public class CoSignTest {
private static final String INPUT = "D:\\tmp\\demo.pdf";
private static final String PRECONTENT = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
"<request>\n" +
" <Logic>\n" +
" <allowAdHoc>true</allowAdHoc>\n" +
" <workingMode>pull</workingMode>\n" +
" <enforceReason>false</enforceReason>\n" +
" </Logic>\n" +
" <Url>\n" +
" <finishURL>http://localhost:64956/retrieveSignedFile.aspx</finishURL>\n" +
" </Url>\n" +
" <Document>\n" +
" <fileID>1234567890</fileID>\n" +
" <contentType>pdf</contentType>\n" +
" <content>";
private static final String POSTCONTENT = "</content>\n" +
" </Document>\n" +
"</request>";
private static final String POST_URL = "https://webagentdev.arx.com/Sign/UploadFileToSign";
private static final String PULL_URL = "https://webagentdev.arx.com/Sign/DownloadSignedFileG";
public static final int TIMEOUT = 300000;
public static void main(String[] args) throws Exception {
InputStream is = new FileInputStream(INPUT);
String content = PRECONTENT + new String(Base64.encodeBase64(loadResource(is)), "UTF-8") + POSTCONTENT;
System.out.println(content);
String reply = new String(sendDocForProcessing(URLEncoder.encode(content, "UTF-8")));
System.out.println(reply);
System.out.println("DONE");
}
private static String sendDocForProcessing(String content) throws Exception {
HttpClient client = null;
HttpMethodBase method = null;
SimpleHttpConnectionManager mgr = new SimpleHttpConnectionManager();
String reply = "";
try {
mgr.getParams().setConnectionTimeout(TIMEOUT);
mgr.getParams().setSoTimeout(TIMEOUT);
client = new HttpClient(mgr);
method = new PostMethod(POST_URL);
method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(1, false));
method.getParams().setParameter("http.socket.timeout", TIMEOUT);
client.getHttpConnectionManager().getParams().setConnectionTimeout(TIMEOUT);
client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
method.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
method.getParams().setParameter("inputXML", content);
client.executeMethod(method);
reply = new String(method.getResponseBody());
} catch (Exception e) {
e.printStackTrace();
} finally {
if(method != null) {
method.releaseConnection();
}
client = null;
mgr.shutdown();
}
if (isSigningSuccessful(reply)) {
return reply;
} else {
throw new Exception("Failed in signing the document. Error: " + reply);
}
}
private static boolean isSigningSuccessful(String reply) throws ParserConfigurationException, IOException, SAXException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new ByteArrayInputStream(reply.getBytes()));
Element elem = doc.getDocumentElement();
String type = elem.getAttribute("type");
return !"error".equals(type);
}
public static byte[] loadResource(InputStream in) {
if (in == null) {
return new byte[0];
}
try {
int indice, tempIndice;
byte[] tempArr;
byte[] mainArr = new byte[0];
byte[] byteArr = new byte[65535];
for (indice = 0; (indice = in.read(byteArr)) > 0;) {
tempIndice = mainArr.length + indice;
tempArr = new byte[tempIndice];
System.arraycopy(mainArr, 0, tempArr, 0, mainArr.length);
System.arraycopy(byteArr, 0, tempArr, mainArr.length, indice);
mainArr = tempArr;
}
in.close();
return mainArr;
} catch (Exception e) {
e.printStackTrace();
}
return new byte[0];
}
}
Thanks for adding your Java code. Note that the HttpClient
instance is configured incorrectly and as a result the http-post request is sent empty. Take a look at the modifications I did in your sendDocForProcessing
function in order to properly post the XML content:
private static String sendDocForProcessing(String content) throws Exception {
HttpClient client = null;
PostMethod method = null;
String reply = "";
try {
client = new HttpClient();
method = new PostMethod(POST_URL);
method.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
NameValuePair[] data = { new NameValuePair("inputXML", content) };
method.setRequestBody(data);
client.executeMethod(method);
reply = method.getResponseBodyAsString();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(method != null) {
method.releaseConnection();
}
}
if (isSigningSuccessful(reply)) {
return reply;
} else {
throw new Exception("Failed in signing the document. Error: " + reply);
}
}
The content passed to the above function should not be URL-encoded as it is already done by the HttpClient
library.
In addition, when analyzing the response, I suggest you to check the value of the returnCode
element rather than the type
property. The response is always of type 'error'.
Also note that the function name isSigningSuccessful
is misleading as this stage is still prior to the act of signing.