Можно ли отправить ответ с XPage, использующего Transfer-Encoding:chunked

Моя цель - передать большой ответ браузеру. Мне нужно свести к минимуму использование памяти XPage, чтобы множественные обращения не вывели сервер из строя. XPages настроены в стиле «XAgent» с рендерингом = false.

У кого-нибудь это работает?

Попытка 1

Согласно различным сообщениям HttpServletResponse, это должно быть так же просто, как сбросить средство записи по мере продвижения, но это не так. Приведенный ниже код включает закомментированный раздел под названием Experiment1, который я использовал, чтобы намеренно нарушить ответ. Моя логика заключается в том, что вызов resetBuffer не должен влиять на контент, который я уже «сбросил», но он повлиял. Сломанный ответ включал только сообщение об ошибке и ни один из фрагментов. Есть большая вероятность, что мое предположение, конечно, неверно. Код выполнялся в событии afterRenderResponse.

importPackage(java.util);
importPackage(java.io);
importPackage(java.lang);

var ec=facesContext.getExternalContext();
var response=ec.getResponse();
var request=ec.getRequest();
var writer=facesContext.getResponseWriter();
try{
    response.setHeader("Content-Type","text/plain; charset=utf-8");

    for(var i=0;i<100;i++){
        var s="CHUNKCHUNKCHUNK"+i;
        writer.write(s);
        writer.flush();
        response.flushBuffer();
        //EXPERIMENT1
        //if(i==50){
            //throw new Error("FAIL ON PURPOSE")
        //}
    }

}catch(e){
    //EXPERIMENT1
    //response.resetBuffer()

    var errorObj={};
    response.setStatus(500);

    var errorMessage = e.message;

    if( typeof e.printStackTrace !== 'undefined' ){
        var stringWriter = new java.io.StringWriter();
        e.printStackTrace( new java.io.PrintWriter( stringWriter ) );
        errorMessage = stringWriter.toString();
    }

    if( typeof e === 'com.ibm.jscript.InterpretException' ){
        errorMessage = e.getNode().getTraceString() + '\n\n' + errorMessage;
    }

    errorObj.status="error";
    errorObj.message=errorMessage;
    writer.write(toJson(errorObj));
}finally{
    if(creport!=null){
        if(debug){
            creport.close(true);
        }else{
            creport.closeOnlyIfIssue(true);
        }
    }
    facesContext.responseComplete();
}

Попытка 2

Моя вторая попытка была чистым отчаянием. Он использует событие beforeRenderResponse и записывает фрагменты в соответствии со спецификацией HTML1.1. В приведенном ниже коде заголовок «Transfer-Encoding» закомментирован, поскольку он приводит к полезной нагрузке с нулевым байтом. Заголовки делают это, хотя ..

importPackage(java.util);
importPackage(java.io);
importPackage(java.lang)

var ec=facesContext.getExternalContext();
var response=ec.getResponse();
var request=ec.getRequest();
var writer=response.getOutputStream();
try{
    response.setHeader("Content-Type","text/plain; charset=utf-8");
    //response.setHeader("Transfer-Encoding","chunked")
    response.setBufferSize(1024);
    for(var i=0;i<100;i++){
        var s="CHUNKCHUNKCHUNK"+i;
        writer.write((Integer.toHexString(s.length())+"\r\n").getBytes("utf-8"));
        writer.write((s+"\r\n").getBytes("utf-8"));
        writer.flush();
        response.flushBuffer();
    }
    writer.write("0\r\n\r\n".getBytes("utf-8"))

}catch(e){
    var errorObj={};
    //response.resetBuffer();
    response.setStatus(500);

    var errorMessage = e.message;

    if( typeof e.printStackTrace !== 'undefined' ){
        var stringWriter = new java.io.StringWriter();
        e.printStackTrace( new java.io.PrintWriter( stringWriter ) );
        errorMessage = stringWriter.toString();
    }

    if( typeof e === 'com.ibm.jscript.InterpretException' ){
        errorMessage = e.getNode().getTraceString() + '\n\n' + errorMessage;
    }

    errorObj.status="error";
    errorObj.message=errorMessage;
    writer.write(toJson(errorObj).getBytes("utf-8"));
}finally{
    facesContext.responseComplete();
}

person Brendan Wheble    schedule 29.07.2015    source источник
comment
Я никогда не пробовал, но для чего-то подобного я бы попробовал способ сервлета (см. edm00se.io/xpages-servlets/ для вдохновения). Это дает вам гораздо больший контроль над объектом ответа по сравнению с агентами XAgent, которые сами выполняют часть построения ответа.   -  person Mark Leusink    schedule 29.07.2015


Ответы (1)


При доступе к ответу с помощью

var response=ec.getResponse()

вы получаете экземпляр com.ibm.xsp.webapp.XspHttpServletResponse. Он использует внутренний механизм буфера/блока для повышения производительности, поэтому ваш первый эксперимент не работает должным образом.

Но если вы обращаетесь к базовому LCDAdapterHttpServletResponse напрямую, можно получить полный контроль над выходным потоком:

var response=ec.getResponse().getDelegate();
person Sven Hasselbach    schedule 30.07.2015
comment
Вызов getDelegate() сделал свое дело. Смотрите мой измененный код ниже - person Brendan Wheble; 30.07.2015