2010-07-28 31 views

Respuesta

19

Desafortunadamente, esto no es posible en la implementación estándar de JSF. El componente y el procesador no admiten oficialmente este atributo. Sin embargo, puedes hacer un homegrow de un renderizador que maneje esto.

Dado que este es un requisito/deseo bastante común, pensé echar un vistazo a lo que es posible.

Primero algo de información de fondo: JSF utiliza de forma predeterminada ResponseWriter#writeText() para escribir el cuerpo de la etiqueta, que escapa HTML de forma predeterminada. Nos gustaría dejar que use ResponseWriter#write() como en el caso de <h:outputText escape="false" />. Nos gustaría extender el MessagesRenderer de la implementación JSF estándar y anular el método encodeEnd() en consecuencia. Pero como el MessagesRenderer#encodeEnd() contiene bastante código (~ 180 líneas) que preferimos no copiar para simplemente cambiar una o dos líneas después de todo, me pareció mejor reemplazar el ResponseWriter con una implementación personalizada con la ayuda de ResponseWriterWrapper donde writeText() ha sido anulado para manejar el escape.

Así, terminé con esto:

package com.example; 

import java.io.IOException; 

import javax.faces.component.UIComponent; 
import javax.faces.context.FacesContext; 
import javax.faces.context.ResponseWriter; 
import javax.faces.context.ResponseWriterWrapper; 
import javax.faces.render.FacesRenderer; 

import com.sun.faces.renderkit.html_basic.MessagesRenderer; 

@FacesRenderer(componentFamily="javax.faces.Messages", rendererType="javax.faces.Messages") 
public class EscapableMessagesRenderer extends MessagesRenderer { 

    @Override 
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException { 
     final ResponseWriter originalResponseWriter = context.getResponseWriter(); 

     try { 
      context.setResponseWriter(new ResponseWriterWrapper() { 

       @Override 
       public ResponseWriter getWrapped() { 
        return originalResponseWriter; 
       } 

       @Override 
       public void writeText(Object text, UIComponent component, String property) throws IOException { 
        String string = String.valueOf(text); 
        String escape = (String) component.getAttributes().get("escape"); 
        if (escape != null && !Boolean.valueOf(escape)) { 
         super.write(string); 
        } else { 
         super.writeText(string, component, property); 
        } 
       } 
      }); 

      super.encodeEnd(context, component); // Now, render it! 
     } finally { 
      context.setResponseWriter(originalResponseWriter); // Restore original writer. 
     } 
    } 
} 

A pesar de la @FacesRenderer anotación, se consiguen anulado por el MessagesRenderer implementación por defecto. Sospecho que aquí hay un error, así que informé issue 1748. Para conseguir que funcione de todos modos, tenemos que recurrir a la faces-config.xml:

<render-kit> 
    <renderer> 
     <component-family>javax.faces.Messages</component-family> 
     <renderer-type>javax.faces.Messages</renderer-type> 
     <renderer-class>com.example.EscapableMessagesRenderer</renderer-class> 
    </renderer> 
</render-kit> 

Luego, para activarlo, simplemente hacer:

<h:messages escape="false" /> 

Y funciona! :)


Nota: lo anterior afecta <h:messages> solamente. Para hacer lo mismo con <h:message>, simplemente haga lo mismo, pero reemplace en cualquier parte"Messages" por "Message" (familia de componentes, tipo de procesador y nombres de clase).

+0

Gracias BalusC, hoy también he llegado a la misma solución (y he archivado el mismo error https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=1750) Utilicé el patrón del delegador para mi escritor de respuestas, pero creo que prefiero lo que hiciste con el contenedor. ¡Gracias! –

+0

Un nuevo enlace para el problema informado: http://java.net/jira/browse/JAVASERVERFACES-1750 –

+0

funciona perfectamente BalusC, gracias! –

1

El atributo escape="false" que necesita es proporcionado por OmniFaces <o:messages> component. La biblioteca de utilidades OmniFaces está disponible para JSF 2.

He publicado esta solución mencionada por el comentario de @ BalusC como una respuesta ya que esta es la solución más directa.

Cuestiones relacionadas