Hi there,


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.