Your API REST is real good, and I have almost finished the implementation of a single Java client to consume most of your methods, but I have found only one problem with the submission files POST method. Due to technical restrictions Im not allowed to use
CURL so I have to use HttpURLConnection and Im receiving constantly a response with 400 Error. After reading the PHP definition I have wrote this quite common Java method:
....
private void testConsumerPOST(String array, String nombreProblema, String languageId, String contest_id) {
String servletURL = "http://localhost/domjudge/api/submissions";
URL servlet = null;
try {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
servlet = new URL(servletURL);
HttpURLConnection servletConnection = (HttpURLConnection) servlet.openConnection();
// AUTENTICACION
String userpass = "admin:admin";
String basicAuth = "Basic " + new String(new com.sun.org.apache.xerces.internal.impl.dv.util.Base64().encode(userpass.getBytes()));
servletConnection.setRequestProperty("Authorization", basicAuth);
servletConnection.setRequestMethod("POST");
servletConnection.setDoOutput(true);
servletConnection.setDoInput(true);
OutputStreamWriter out = new OutputStreamWriter(servletConnection.getOutputStream());
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> data = new HashMap<String, Object>();
data.put("code[]", array);
data.put("shortname", nombreProblema);
data.put("langid", languageId);
data.put("contest", contest_id);
out.write(mapper.writeValueAsString(data));
out.flush();
if (
servletConnection.getResponseCode() != HttpURLConnection.HTTP_CREATED) {
throw new RuntimeException("Failed : HTTP error code : "
+ servletConnection.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader(
(servletConnection.getInputStream())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
}
out.close();
} catch (MalformedURLException ex) {
Logger.getLogger(PostSubmission.class.getName()).log(Level.SEVERE, null, ex);
} catch (ProtocolException ex) {
Logger.getLogger(PostSubmission.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(PostSubmission.class.getName()).log(Level.SEVERE, null, ex);
} catch (KeyManagementException ex) {
Logger.getLogger(PostSubmission.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(PostSubmission.class.getName()).log(Level.SEVERE, null, ex);
}
}
Also another one with binary data post almost identical:
private void testConsumerPOST_Binary(String array, String nombreProblema, String languageId, String contest_id) {
String servletURL = "http://192.168.1.146/domjudge/api/submissions";
try {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
HttpURLConnection httpcon = (HttpURLConnection) ((new URL(servletURL).openConnection()));
httpcon.setDoOutput(true);
httpcon.setRequestProperty("Content-Type", "application/json");
httpcon.setRequestProperty("Accept", "application/json");
httpcon.setRequestMethod("POST");
String userpass = "admin:admin";
String basicAuth = "Basic " + new String(new com.sun.org.apache.xerces.internal.impl.dv.util.Base64().encode(userpass.getBytes()));
httpcon.setRequestProperty("Authorization", basicAuth);
httpcon.connect();
ObjectMapper mapper = new ObjectMapper(); //Jackson Object mapper
Map<String, Object> data = new HashMap<String, Object>();
data.put("code[]", array);
data.put("shortname", nombreProblema);
data.put("langid", languageId);
data.put("contest", contest_id);
byte[] outputBytes = mapper.writeValueAsString(data).getBytes("UTF-8");
OutputStream os = httpcon.getOutputStream();
os.write(outputBytes);
os.flush();
if (httpcon.getResponseCode() != HttpURLConnection.HTTP_CREATED) {
throw new RuntimeException("Failed : HTTP error code : "
+ httpcon.getResponseCode());
}
//Get the new submission_id
BufferedReader br = new BufferedReader(new InputStreamReader(
(httpcon.getInputStream())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
}
os.close();
} catch (MalformedURLException ex) {
Logger.getLogger(PostSubmission.class.getName()).log(Level.SEVERE, null, ex);
} catch (ProtocolException ex) {
Logger.getLogger(PostSubmission.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(PostSubmission.class.getName()).log(Level.SEVERE, null, ex);
} catch (KeyManagementException ex) {
Logger.getLogger(PostSubmission.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(PostSubmission.class.getName()).log(Level.SEVERE, null, ex);
}
}
None of them are able to submit the files, just to be clear about the data format Im sending:
code[] ---> "
[{\"filename\":\"main.cpp\",\"content\":\"I2luY2x1ZGUgPGlvc3RyZWFtPg0KI2luY2x1ZGUgPHN0ZGlvLmg+DQoNCnVzaW5nIG5hbWVzcGFjZSBzdGQ7DQoNCmludCBtYWluKCkNCnsNCiAgICBTdHJpbmcgbm9tYnJlPSJwZWRybyI7DQoJaW50IHZhbD0xLHZhMj0xMCx0b3RhbD0wOw0KCXRvdGFsPXZhbCt2YWwyOw0KCQ0KCQ0KICAgIHJldHVybiAwOw0KfQ0K\"}]"
shortname ---> The problem ddbb shortname value previously recovered with the "problems GET method of the API REST"
langid---> The language id value previously recovered with the "problems GET method of the API REST" (Ex: cpp)
contest ---> We have tried both contestId and contest_short_name. Im not sure wich one should be sent.
My last question is: Is the teamId necessary for the post?
We would thank any of your comments to finish this amazing program!!!
Thanks in advance
Javier.