Поймать исключение streamingoutput

Я видел много примеров использования StreamingOutput. В моем случае я хочу использовать его для потоковой передачи ResultSet из запроса к базе данных.

ResultSet rs = (ResultSet) obj;
StreamingOutput stream = new StreamingOutput() {
    @Override
    public void write(OutputStream os) throws IOException,
                                       WebApplicationException {
        ResultSetFormatter.outputAsJSON(os, rs);

        res.close();
    }
};

return Response.ok(stream).build();

В этом смысле определение метода write включает throws IOException, WebApplicationException. Вот где возникает моя проблема. Мне нужно правильно закрыть соединение с базой данных, набором результатов и т. Д. И если во время потоковой передачи возникает исключение, я не знаю, как его захватить.

Я пробовал следующее, но это недопустимый код, поскольку IOException не выбрасывается из блока try-catch.

try {
    ....  launch request to database ...
    ResultSet rs = (ResultSet) obj;
    StreamingOutput stream = new StreamingOutput() {
        @Override
        public void write(OutputStream os) throws IOException,
                                           WebApplicationException {
            if (accept.equals("application/json") {
                ResultSetFormatter.outputAsJSON(os, rs);
            } else {
                ResultSetFormatter.outputAsXML(os, rs);
            }

            res.close();
        }
    };

    return Response.ok(stream).build();
} catch (IOException | WebApplicationException e) {
    // Do cleanup
}

Как я могу продолжить? Можно ли все как следует почистить? Я даже подумал о том, чтобы включить всю обработку данных в метод write, но проблема в том, что тогда я не могу установить Content-type ответа, если он не исправлен.

TIA

Изменить 1: я использую предложения SPARQL на основе Jena, а не базы данных SQL. В зависимости от типа запроса я получаю разные типы ответов (модель, набор результатов или логическое значение). Тогда у каждого из них есть разные допустимые типы контента, поэтому я не могу установить тип контента ответа, пока запрос не будет выполнен или проанализирован.


person jlanza    schedule 19.09.2017    source источник
comment
Чего вы здесь пытаетесь достичь? В чем работает этот код? Похоже, вы пытаетесь скопировать ленивую загрузку данных. Вероятно, есть более эффективные способы добиться этого.   -  person LAROmega    schedule 19.09.2017
comment
У меня есть большой набор результатов, который в противном случае мне придется хранить локально в памяти. Я хочу передать его прямо клиенту. Проблема возникает в случае, если что-то произойдет, так как мне нужно закрыть набор результатов и т.д., чтобы освободить ресурсы. Я не понимаю твою ленивую загрузку данных.   -  person jlanza    schedule 19.09.2017
comment
См. Эту ветку для объяснения ленивой загрузки.   -  person LAROmega    schedule 19.09.2017
comment
Не думаю, что это ленивая загрузка. Как я уже говорил, я не хочу хранить в памяти весь набор результатов для создания строки. Я предпочитаю транслировать его напрямую.   -  person jlanza    schedule 19.09.2017
comment
Похоже, вы хотите загрузить данные, когда они используются, вместо того, чтобы загружать все, а затем передавать данные в ответ вашего веб-сервиса, то есть ленивая загрузка. В любом случае, если оставить в стороне семантику, обычно вы хотите, чтобы ваша служба обрабатывала транзакцию базы данных для каждого запроса. Это сохранит ваши результаты до тех пор, пока они не будут использованы. Трудно вдаваться в подробности, не зная, используете ли вы какие-либо фреймворки, или это сервлет, или что-то еще.   -  person LAROmega    schedule 19.09.2017
comment
По мере обновления (редактировать 1) я использую Jena для SPARQL. В этом случае значения набора результатов извлекаются на каждой итерации, и поэтому нет необходимости хранить все в памяти.   -  person jlanza    schedule 20.09.2017


Ответы (2)


Вы можете проверить try-with-resources, это автоматически закрывает это для вас.

До Java SE 7 можно было пройти через finally . Он выполняется независимо от точки выхода try.

person Dimitar    schedule 19.09.2017
comment
У меня была эта попытка с ресурсами, но проблема в том, что набор результатов затем близок, поскольку поток - это то, что выполняется после возврата, а затем, когда вызывается запись StreamingOutput, он жалуется, что набор результатов больше недействителен. Так что это не актуально для меня :( - person jlanza; 19.09.2017

user8 был прав, но не сообщил подробностей. Вы хотите, чтобы ваш оператор try-with-resources находился внутри вашего write метода:

@Override
public void write(OutputStream os) throws IOException,
                                   WebApplicationException {

    try (Statement statement = rs.getStatement();
         Connection conn = statement.getConnection()) {

        if (accept.equals("application/json") {
            ResultSetFormatter.outputAsJSON(os, rs);
        } else {
            ResultSetFormatter.outputAsXML(os, rs);
        }
    }
}

При автоматическом закрытии Заявления автоматически закроется ResultSet.

person VGR    schedule 19.09.2017
comment
Это верно, но проблема в том, что значение accept извлекается в зависимости от типа ответа на запрос. Я использую Sparql, а не SQL, и могу получать разные типы ответов (модель, набор результатов или логическое значение). Я обновил свой вопрос. - person jlanza; 19.09.2017