FileNotFoundException при получении объекта InputStream из HttpURLConnection

Я пытаюсь отправить почтовый запрос на URL-адрес, используя HttpURLConnection (для использования cUrl в java). Содержимое запроса - xml, а в конечной точке приложение обрабатывает xml и сохраняет запись в базе данных, а затем отправляет ответ в виде строки xml. Приложение размещено на apache-tomcat локально.

Когда я выполняю этот код с терминала, строка добавляется в db, как и ожидалось. Но исключение бросается следующим образом, получая InputStream из соединения

java.io.FileNotFoundException: http://localhost:8080/myapp/service/generate
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1401)
    at org.kodeplay.helloworld.HttpCurl.main(HttpCurl.java:30)

Вот код

public class HttpCurl {
    public static void main(String [] args) {

        HttpURLConnection con;

        try {
            con = (HttpURLConnection) new URL("http://localhost:8080/myapp/service/generate").openConnection();
            con.setRequestMethod("POST");
            con.setDoOutput(true);
            con.setDoInput(true);

            File xmlFile = new File("test.xml");

            String xml = ReadWriteTextFile.getContents(xmlFile);                

            con.getOutputStream().write(xml.getBytes("UTF-8"));
            InputStream response = con.getInputStream();

            BufferedReader reader = new BufferedReader(new InputStreamReader(response));
            for (String line ; (line = reader.readLine()) != null;) {
                System.out.println(line);
            }
            reader.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  }

Это сбивает с толку, потому что исключение прослеживается к строке InputStream response = con.getInputStream();, и, похоже, для исключения FileNotFoundException не существует никакого файла.

Когда я пытаюсь открыть соединение с xml файлом напрямую, он не генерирует это исключение.

В приложении службы используется инфраструктура spring и Jaxb2Marshaller для создания ответа xml.

Класс ReadWriteTextFile взят из здесь

Спасибо.

Edit: Ну, это сохраняет данные в БД и одновременно отправляет обратно код статуса ответа 404.

Я также попытался сделать завиток, используя php, и распечатать CURLINFO_HTTP_CODE, который окажется равным 200.

Любые идеи о том, как я могу отлаживать это? Оба сервиса и клиент находятся на локальном сервере.

Решено: Я мог бы решить проблему, обратившись к ответу на сам SO.

Кажется, HttpURLConnection всегда возвращает 404 ответ при подключении к URL-адресу с нестандартным портом.

Добавление этих строк разрешило его

con.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) ");
con.setRequestProperty("Accept","*/*");

Ответ 1

Я не знаю о вашей комбинации Spring/JAXB, но средний веб-сервис REST не вернет тело ответа в POST/PUT, просто статус ответа. Вы хотите определить его вместо тела.

Заменить

InputStream response = con.getInputStream();

по

int status = con.getResponseCode();

Все доступные коды состояния и их значение доступны в спецификации HTTP, как было указано ранее. Сам веб-сервис должен также содержать некоторую документацию, которая просматривает все коды состояния, поддерживаемые webservice, и их особое значение, если таковые имеются.

Если статус начинается с 4nn или 5nn, вы хотели бы использовать getErrorStream() вместо этого, чтобы прочитать тело ответа, которое может содержать сведения об ошибке.

InputStream error = con.getErrorStream();

Ответ 2

FileNotFound является просто неудачным исключением, используемым для указания того, что веб-сервер возвратил 404.

Ответ 3

Кому-нибудь с этой проблемой в будущем, причина в том, что код состояния был 404 (или в моем случае был 500). Похоже, что функция InpuStream выдаст ошибку, если код состояния не равен 200.

В моем случае я управляю своим собственным сервером и возвращаю код состояния 500, чтобы указать на возникшую ошибку. Несмотря на то, что я также отправил тело с строковым сообщением с подробным описанием ошибки, inputstream выбрал ошибку, несмотря на то, что тело полностью читаемо.

Если вы управляете своим сервером, я полагаю, что это можно обработать, отправив себе код состояния 200, а затем обработав любой ответ на строковый ответ.

Ответ 4

Для кого-то другого, споткнувшегося об этом, то же самое произошло со мной при попытке отправить заголовок запроса SOAP службе SOAP. Проблема была неправильным порядком в коде, я попросил входной поток сначала перед отправкой тела XML. В приведенном ниже коде строка InputStream in = conn.getInputStream(); появилась сразу после ByteArrayOutputStream out = new ByteArrayOutputStream();, которая является неправильным порядком вещей.

ByteArrayOutputStream out = new ByteArrayOutputStream();
// send SOAP request as part of HTTP body 
byte[] data = request.getHttpBody().getBytes("UTF-8");
conn.getOutputStream().write(data); 

if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
  Log.d(TAG, "http response code is " + conn.getResponseCode());
  return null;
}

InputStream in = conn.getInputStream();

FileNotFound в этом случае был неудачным способом кодирования кода ответа HTTP 400.

Ответ 5

FileNotFound в этом случае означает, что вы получили 404 с вашего сервера - может быть, сервер не любит запросы "POST"?

Ответ 6

Решение:
просто измените localhost на IP вашего ПК.
если вы хотите это знать: Windows + r > cmd > ipconfig
Пример: http:// 192.168.0.107/directory/service/program.php?action=sendSomething
просто замените 192.168.0.107 на свой собственный IP-адрес (не пытайтесь 127.0.0.1, потому что он такой же, как localhost)

Ответ 7

Измените

con = (HttpURLConnection) new URL("http://localhost:8080/myapp/service/generate").openConnection();

Для

con = (HttpURLConnection) new URL("http://YOUR_IP:8080/myapp/service/generate").openConnection();