Pregunta

Tengo un commandButton que invocará una función para descargar un archivo (telas estándar como InputStream, BufferedOutputStream ...) Después de la descarga éxito, al final de la función, que cambiar algunos valores del objeto actual y persistir en base de datos. Todos estos trabajos correctamente. Ahora, cuando la descarga de archivos es hecho esto, el contenido de la página no se actualiza. Tengo que golpear de refresco para mí ver el contenido actualizado. Por favor ayuda. A continuación se presentan la estructura básica de mi código

document: Bean administrado
getDrawings(): método devuelve una lista de Dibujo (clase de entidad)
CheckedOutBy: atributo de la entidad Drawing

<p:dataTable id="drawing_table" value="#{document.drawings}" var="item" >                            
    <p:column>
        <f:facet name="header">
              <h:outputText value="CheckedOutBy"/>
        </f:facet>
        <h:outputText value="#{item.checkedOutBy}"/>
        ...
</p:dataTable>
<p:commandButton ajax="false" action="#{document.Download}" value="Download" />

Dentro de mi bean gestionado

public void Download(){
    Drawing drawing = getCurrentDrawing();
    //Download drawing
    drawing.setCheckedOutBy("Some Text");
    sBean.merge(drawing);  //Update "Some Text" into CheckedOutBy field
}
¿Fue útil?

Solución

Se podría básicamente como para dejar que el fuego cliente dos peticiones. Uno para recuperar la descarga y la otra para actualizar la nueva página. Ellos no se pueden realizar en una sola petición HTTP. Dado que las necesidades de descarga que deben tomarse de forma sincronizada y no hay manera de conectar el total de la descarga desde el lado del cliente en, no hay JSF limpia / maneras JS / Ajax para actualizar un componente en completa de la descarga.

Su mejor JSF-bet con ayuda de PrimeFaces es <p:poll>

<h:outputText id="checkedOutBy" value="#{item.checkedOutBy}"/>
...
<p:poll id="poll" interval="5" update="checkedOutBy" />

o <p:push>

<p:push onpublish="javaScriptFunctionWhichUpdatesCheckedOutBy" />  

El sondeo es fácil, pero puedo imaginar que implica una sobrecarga innecesaria. No se puede iniciar utilizando componentes estándar de JSF / PrimeFaces Cuando la descarga se inicia síncronos. Pero se puede detener a dejar que haga una auto-comprobación en el atributo rendered. Empujar es técnicamente la mejor solución, pero más resistente a empezar con. PrimeFaces explica su uso sin embargo muy bien en el capítulo 6 de la Guía del usuario.

Otros consejos

Bueno, decidió ir con respuesta / recomendación anterior de BalusC, y decidió compartir mi código aquí para la gente que puede pasar por aquí, 'más tarde'. Para su información, más detalles de entorno son a continuación:

TomEE 1.6.0 INSTANTÁNEA (Tomcat 7.0.39), 3,5 (PrimeFaces PrimeFaces Push), Ambiente 1.0.13 instantánea (1.0.12 es la última versión estable)

En primer lugar, estoy usando p: FileDownload con p:. CommandLink

<p:commandLink value="Download" ajax="false"
               actionListener="#{pf_ordersController.refreshDriverWorksheetsToDownload()}">
    <p:fileDownload value="#{driverWorksheet.file}"/>
</p:commandLink>

Desde que tengo el XHTML anterior, y dado que p: FileDownload no permite onComplete = "someJavaScript ()" para ser ejecutado, que decidió utilizar PrimeFaces Push to mensaje de inserción de cliente, para activar el javascript necesario para desbloquear la interfaz de usuario , ya que la interfaz de usuario estaba siendo bloqueado cada vez que haga clic en el commandLink de descarga de archivos, y durante muchos meses, no sabía cómo resolver esto.

Desde ya estoy usando PrimeFaces empuje, que tuvo que ajustar lo siguiente en el lado del cliente:

.js; método que contiene mensajes manijas empujados desde el servidor al cliente

function handlePushedMessage(msg) {
    /* refer to primefaces.js, growl widget,
     * search for: show, renderMessage, e.detail
     * 
     * sample msg below:
     * 
     * {"data":{"summary":"","detail":"displayLoadingImage(false)","severity":"Info","rendered":false}}
     */
    if (msg.detail.indexOf("displayLoadingImage(false)") != -1) {
        displayLoadingImage(false);
    }
    else {
        msg.severity = 'info';
        growl.show([msg]);
    }
}

index.xhtml; contiene p: componente socket (PrimeFaces Push); Recomiendo todos los siguientes, si estás a implementar ejemplo FacesMessage de PrimeFaces Empuje

<h:outputScript library="primefaces" name="push/push.js" target="head" />
<p:growl id="pushedNotifications" for="socketForNotifications"
         widgetVar="growl" globalOnly="false"
         life="30000" showDetail="true" showSummary="true" escape="false"/>
<p:socket id="socketForNotifications" onMessage="handlePushedMessage"
          widgetVar="socket"
          channel="/#{pf_usersController.userPushChannelId}" />

meses (o tal vez un año o menos) hace, he encontrado que es necesario añadir lo siguiente a la commandLink que envuelve t: FileDownload, que refrescará el archivo / corriente en el servidor, por lo que puede hacer clic en el archivo tantas veces como sea necesario para descargar el archivo y otra vez sin actualizar la página a través de la tecla F5 / refresco en el teclado (o similar en el dispositivo móvil)

actionListener="#{pf_ordersController.refreshDriverWorksheetsToDownload()}"

Se hace referencia Ese método frijol cada vez que hace clic en el usuario final commandLink, para descarga de archivos, así que era perfecto lugar para 'empujar' un mensaje del servidor al cliente, a javascript gatillo de cliente, para desbloquear la interfaz de usuario.

A continuación se presentan los métodos de frijol en mi aplicación que hace el trabajo. :)

pf_ordersController.refreshDriverWorksheetsToDownload ()

public String refreshDriverWorksheetsToDownload() {
    String returnValue = prepareDriverWorksheetPrompt("download", false);
    usersController.pushNotificationToUser("displayLoadingImage(false)");
    return returnValue;
}

usersController.pushNotificationToUser (); He tenido que añadir éste, esta noche.

public void pushNotificationToUser(String notification) {
    applicationScopeBean.pushNotificationToUser(notification, user);
}

applicationScopeBean.pushNotificationToUser (); esto ya existía, ningún cambio a este método.

public void pushNotificationToUser(String msg, Users userPushingMessage) {
    for (SessionInfo session : sessions) {
        if (userPushingMessage != null &&
            session.getUser().getUserName().equals(userPushingMessage.getUserName()) &&
            session.getUser().getLastLoginDt().equals(userPushingMessage.getLastLoginDt())) {
            PushContext pushContext = PushContextFactory.getDefault().getPushContext();
            pushContext.push("/" + session.getPushChannelId(),
                             new FacesMessage(FacesMessage.SEVERITY_INFO, "", msg));
            break;
        }
    }
}

Se puede usar el atributo update del componente p:commandButton que volver a hacer el área que tiene la intención de actualizar después de la descarga, en este caso el "drawing_table".

<p:commandButton update="drawing_table" action="#{document.Download}" value="Download" />

Balusc respondido respuesta, no podemos obtener el doble de una única solicitud.

Para actualizar una página después de la descarga, utilizar mejor la siguiente secuencia de comandos Java en enlace de descarga (p:commandbutton) etiqueta onclick .

Ejemplo:

<p:commandButton ajax="false" icon="ui-icon-arrowstop-1-s" onclick="setTimeout('location.reload();', 1000);" action="#{managedBean.downloadMethod}" />

Esto actualizará automáticamente la página después de 1 segundo, al mismo tiempo, es decir, antes de refresco, obtendrá el archivo de descarga, en función de su tiempo de respuesta de descarga, aumentar los segundos en ese guión. segundos no debe menos que el tiempo de respuesta de descargas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top