Моя установка. Я создал службу REST (Jersey/Dropwizard), которая выполняет потоковую передачу большого содержимого из базы данных. Во время операции GET служба подключается к базе данных через пул соединений, упаковывает данные в поток и выполняет некоторые преобразования «на лету» для отображения запрошенных данных в различных кодировках (CSV, JSON, ...). Время жизни соединения с базой данных привязано к времени жизни потока, и только когда поток закрывается, соединение с базой данных освобождается.
Потоковое преобразование выполняется классом Encoder, который возвращает StreamingOutput, который затем передается объекту Response. В настоящее время кодировщик обрабатывает закрытие ресурсов, когда поток полностью использован.
Моя проблема. Поскольку StreamingOutput не реализует AutoCloseable, возможны утечки соединения, когда вывод используется лишь частично.
Иногда я наблюдаю, что устаревшие активные соединения накапливаются в пуле соединений, и я подозреваю, что они возникают из-за прерванных HTTP-соединений. Как видно ниже, текущий код обрабатывает исключения, возникающие в блоке try. Что я не могу обработать, так это исключения, возникающие после оператора return, и я не знаю, как прикрепить какие-либо инструкции по закрытию ресурса к объекту Response.
Мой вопрос: как я могу сообщить объекту Response закрыть определенные ресурсы после завершения запроса (регулярно или из-за ошибки)? Или: есть ли лучший способ безопасно закрыть любые связанные ресурсы, когда контекст запроса заканчивается?
@GET
//@Produces(...)
public Response streamData(
@PathParam("key") String key,
// ... other params
) {
//decode and validate params
Stream<Pojo> ps = null;
try {
// connect to db and obtain data stream for <key>
ps = loadData(db, key);
// apply detailed encoding instrunctions and create a StreamingOutput
final StreamingOutput stream = Encoder.encodeData(ps, encodingArgs);
return Response.ok(stream).build();
} catch (Exception e) {
closeOnException(ps); // wrapper for ps.close();
throw e;
}
}