Pregunta

¿Cuál es la diferencia entre action y actionListener, y cuando debo usar action frente actionListener?

¿Fue útil?

Solución

actionListener

Uso actionListener si usted quiere tener un gancho antes de la acción de negocio reales consiguen ejecutado, por ejemplo, para iniciar la sesión, y / o para establecer una propiedad adicional (por <f:setPropertyActionListener> ), y / o para tener acceso al componente que invoca la acción (que está disponible por ActionEvent argumento). Por lo tanto, puramente para la preparación de los propósitos antes de la acción real de negocios se invoca.

El método actionListener tiene por defecto la firma siguiente:

import javax.faces.event.ActionEvent;
// ...

public void actionListener(ActionEvent event) {
    // ...
}

Y se supone que debe ser declarado de la siguiente manera, sin ningún tipo de método paréntesis:

<h:commandXxx ... actionListener="#{bean.actionListener}" />

Tenga en cuenta que no se puede pasar adicional argumentos de EL 2.2. Sin embargo, puede anular por completo el argumento ActionEvent pasando y especificando argumento a medida (s). Los ejemplos siguientes son válidos:

<h:commandXxx ... actionListener="#{bean.methodWithoutArguments()}" />
<h:commandXxx ... actionListener="#{bean.methodWithOneArgument(arg1)}" />
<h:commandXxx ... actionListener="#{bean.methodWithTwoArguments(arg1, arg2)}" />
public void methodWithoutArguments() {}
public void methodWithOneArgument(Object arg1) {}
public void methodWithTwoArguments(Object arg1, Object arg2) {}

Tenga en cuenta la importancia de los paréntesis en la expresión método argumentless. Si estaban ausentes, JSF todavía esperaría que un método con el argumento ActionEvent.

Si estás en EL 2.2+, entonces se puede declarar varios métodos de acción del oyente a través de <f:actionListener binding>.

<h:commandXxx ... actionListener="#{bean.actionListener1}">
    <f:actionListener binding="#{bean.actionListener2()}" />
    <f:actionListener binding="#{bean.actionListener3()}" />
</h:commandXxx>
public void actionListener1(ActionEvent event) {}
public void actionListener2() {}
public void actionListener3() {}

Tenga en cuenta la importancia de los paréntesis en el atributo binding. Si estaban ausentes, EL confusamente sería lanzar una javax.el.PropertyNotFoundException: Property 'actionListener1' not found on type com.example.Bean, porque el atributo binding por defecto es interpretada como una expresión de valor, no como una expresión de método. Añadiendo paréntesis estilo EL 2.2+ transparente se vuelve una expresión de valor en una expresión método. Ver también a.o. Por la mañana I capaz de unirse ? a un método arbitrario si no está soportado por JSF


acción

Uso action si se desea ejecutar una acción de negocio y si la navegación mango es necesario. El método puede action (por lo tanto, no debe) devolver un String que se utilizará como resultado del caso de navegación (la vista de destino). Un valor de retorno de null o void lo dejará volver a la misma página y mantener el alcance vista actual con vida. Un valor de retorno de una cadena vacía o el mismo ID de vista también regresará a la misma página, pero el alcance de recrear la vista y por lo tanto destruir cualquier vista de ámbito de granos actualmente activos y, en su caso, volver a crearlos.

El método action puede ser cualquier válido MethodExpression , también los que utiliza EL 2,2 argumentos como a continuación:

<h:commandXxx value="submit" action="#{bean.edit(item)}" />

Con este método:

public void edit(Item item) {
    // ...
}

Tenga en cuenta que cuando su método de acción devuelve únicamente una cadena, entonces también puede simplemente especificar exactamente esa cadena en el atributo action. Por lo tanto, esto es totalmente torpe:

<h:commandLink value="Go to next page" action="#{bean.goToNextpage}" />

Con este método sin sentido devolver una cadena codificada:

public String goToNextpage() {
    return "nextpage";
}

En lugar de ello, sólo hay que poner esa cadena hardcoded directamente en el atributo:

<h:commandLink value="Go to next page" action="nextpage" />

Tenga en cuenta que esto a su vez indica un mal diseño: la navegación por correo. Esto no es fácil ni SEO amigable. Todo esto se explica en Cuando debo usar h: outputLink en lugar de h:? commandLink y se supone que hay que resolver como

<h:link value="Go to next page" outcome="nextpage" />

Ver también Cómo navegar en JSF? ¿Cómo hacer URL reflejan página actual (y no uno anterior) .


f: ajax oyente

Desde JSF 2.x hay una tercera vía, la <f:ajax listener>.

<h:commandXxx ...>
    <f:ajax listener="#{bean.ajaxListener}" />
</h:commandXxx>

El método ajaxListener tiene por defecto la firma siguiente:

import javax.faces.event.AjaxBehaviorEvent;
// ...

public void ajaxListener(AjaxBehaviorEvent event) {
    // ...
}

En Mojarra, el argumento AjaxBehaviorEvent es opcional, por debajo de obras como buena.

public void ajaxListener() {
    // ...
}

Pero en MyFaces, sería lanzar una MethodNotFoundException. A continuación trabajos en ambas implementaciones de JSF cuando se quiere omitir el argumento.

<h:commandXxx ...>
    <f:ajax execute="@form" listener="#{bean.ajaxListener()}" render="@form" />
</h:commandXxx>

oyentes Ajax no son realmente útiles en los componentes de mando. Ellos son más útiles en la entrada y seleccionar componentes <h:inputXxx> / <h:selectXxx>. En los componentes de mando, sólo se adhieren a action y / o actionListener para mayor claridad y mejor código autodocumentado. Por otra parte, al igual que actionListener, la f:ajax listener no soporta devolver un resultado de navegación.

<h:commandXxx ... action="#{bean.action}">
    <f:ajax execute="@form" render="@form" />
</h:commandXxx>

Para la explicación en los atributos execute y render, la cabeza a PrimeFaces comprensión de los procesos / actualización y JSF F: ajax ejecutar / procesamiento atributos

.

Invocación fin

Los actionListeners se invoca siempre antes el action en el mismo orden en que se han declarado en la vista y se unen al componente. El f:ajax listener siempre se invoca antes cualquier oyente acción. Por lo tanto, el siguiente ejemplo:

<h:commandButton value="submit" actionListener="#{bean.actionListener}" action="#{bean.action}">
    <f:actionListener type="com.example.ActionListenerType" />
    <f:actionListener binding="#{bean.actionListenerBinding()}" />
    <f:setPropertyActionListener target="#{bean.property}" value="some" />
    <f:ajax listener="#{bean.ajaxListener}" />
</h:commandButton>

invocará los métodos en el orden siguiente:

  1. Bean#ajaxListener()
  2. Bean#actionListener()
  3. ActionListenerType#processAction()
  4. Bean#actionListenerBinding()
  5. Bean#setProperty()
  6. Bean#action()

El manejo de excepciones

El actionListener es compatible con una excepción especial: AbortProcessingException . Si esta excepción se produce a partir de un método de actionListener, a continuación, JSF omitirá cualquier detector de acción restantes y el método de acción y proceder a dar respuesta directa. No verá una página de error / excepción, sin embargo JSF registrarlo. Esto también implícitamente hacerse siempre que cualquier otra excepción está siendo lanzado desde una actionListener. Por lo tanto, si la intención de bloquear la página de una página de error como resultado de una excepción de negocio, entonces usted debería ser realizar el trabajo en el método action.

Si la única razón para utilizar un actionListener es tener un método void regresar a la misma página, entonces eso es una mala. Los métodos action pueden perfectamente también volver void, por el contrario a lo que algunos entornos de desarrollo permiten que usted cree a través de la validación EL. Tenga en cuenta que la PrimeFaces escaparate ejemplos están llenas de este tipo de actionListeners sobre todo lugar. Este es de hecho mal. No utilice esto como una excusa para también hacerlo usted mismo.

En las peticiones Ajax, sin embargo, se necesita un controlador especial de excepción. Esto es independientemente de si utiliza el atributo de listener <f:ajax> o no. Para la explicación y un ejemplo, la cabeza a Ajax solicitudes .

Otros consejos

Como BalusC indicado, la actionListener por excepciones predeterminados tragos, pero en JSF 2.0 hay un poco más a esta. Es decir, no sólo se traga y los registros, pero en realidad publica la excepción.

Esto ocurre a través de una llamada como ésta:

context.getApplication().publishEvent(context, ExceptionQueuedEvent.class,                                                          
    new ExceptionQueuedEventContext(context, exception, source, phaseId)
);

La escucha predeterminado para este evento es la ExceptionHandler que por Mojarra se establece en com.sun.faces.context.ExceptionHandlerImpl. Esta aplicación, básicamente, volver a lanzar ninguna excepción, excepto cuando se trata de un AbortProcessingException, que ha iniciado la sesión. ActionListeners envuelven la excepción que se produce por el código de cliente en un AbortProcessingException tales que explica por qué estos siempre se registran.

Esta ExceptionHandler puede ser reemplazado sin embargo, en faces-config.xml con una implementación personalizada:

<exception-handlerfactory>
   com.foo.myExceptionHandler
</exception-handlerfactory>

En lugar de escuchar a nivel mundial, un solo grano puede también escuchar a estos eventos. La siguiente es una prueba de concepto de esta:

@ManagedBean
@RequestScoped
public class MyBean {

    public void actionMethod(ActionEvent event) {

        FacesContext.getCurrentInstance().getApplication().subscribeToEvent(ExceptionQueuedEvent.class, new SystemEventListener() {

        @Override
        public void processEvent(SystemEvent event) throws AbortProcessingException {
            ExceptionQueuedEventContext content = (ExceptionQueuedEventContext)event.getSource();
            throw new RuntimeException(content.getException());
        }

        @Override
        public boolean isListenerForSource(Object source) {
            return true;
        }
        });

        throw new RuntimeException("test");
    }

}

(nota, esto no es cómo se debe normalmente a los oyentes de código, esto es sólo para fines de demostración!)

Al llamar a este desde un Facelet como esto:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">
    <h:body>
        <h:form>
            <h:commandButton value="test" actionListener="#{myBean.actionMethod}"/>
        </h:form>
    </h:body>
</html>

también se está visualizando una página de error.

ActionListener es despedido en primer lugar, con una opción para modificar la respuesta, antes de la acción se llama y determina la ubicación de la página siguiente.

Si tiene varios botones en la misma página que debería ir al mismo lugar, pero hacer las cosas un poco diferentes, se puede utilizar la misma acción para cada botón, pero el uso de un ActionListener diferente de manejar la funcionalidad ligeramente diferente.

Aquí hay un enlace que describe la relación:

http://www.java-samples.com/showtutorial.php? tutorialid = 605

TL; DR :

Los ActionListeners (no puede haber múltiples) ejecutar en el orden en que fueron registrados antes de la action

Respuesta larga

A action negocio normalmente invoca un servicio EJB y si es necesario también establece el resultado y / o navega final a un punto de vista diferente si eso no es lo que está haciendo un actionListener es decir, más apropiada para cuando el usuario interactúa con los componentes, tales como h:commandButton o h:link que pueden ser manejados por pasar el nombre del método de bean administrado en el atributo actionListener de un componente de interfaz de usuario o de implementar una interfaz ActionListener y pasar el nombre de clase de implementación de atributo actionListener de un componente de interfaz de usuario.

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