2010-06-08 5 views
6

Quiero tener un menú genérico en mi aplicación JSF (MyFaces 1.2).¿Cómo invocar la acción JSF en una clase anónima? EL no puede acceder a él

<h:form> 
    <h:dataTable id="dt1" value="#{portal.actionList}" var="item"> 
    <f:facet name="header"> 
     <h:outputText value="Menu" /> 
    </f:facet> 
    <h:column> 
     <h:commandLink action="#{item.action}"> 
      <h:outputText value="clickme"/> 
     </h:commandLink> 
    </h:column> 
    </h:dataTable> 
</h:form> 

Entonces mi portal en sesión de alcance se vería así:

class Portal { 
    private ArrayList<IAction> list = new ArrayList<IAction>(); 

    public Portal() { 
     list.add(new IAction() { 
       public action() { 
        log.info("called action here"); 
       } 
     }); 
    } 
    public ArrayList<IAction> getActionList() { 
     return list; 
    } 
} 

Cuando ejecuto el código se mostrará bien. Pero cuando intenta ejecutar la acción haciendo clic en el enlace de comando "ClickMe" - se producirá la siguiente excepción:

Class org.apache.el.parser.AstValue can not access a member of class Portal$1 with modifiers "public" 

¿Hay alguna manera de mostrar una lista de las clases anónimas, de las que un método (en este ejemplo ITemplate.action()) ¿se puede ejecutar?

Editar:

Funciona cuando se utiliza una clase (interior). Como por ejemplo:

class Bla implements IAction { 
     public void action() { 
      log.info("yes, i am working"); 
     } 

y en el constructor Portal

public Portal() { 
    list.add(new Bla()); 
} 

Pero esta no es la forma que yo quiero ...

Respuesta

10

Eso es porque las clases anónimas no son accesibles desde el exterior del paquete que contiene la clase anónima.

Aquí es una demostración de lo que está sucediendo detrás de las escenas:

public static void main(String[] args) throws Exception { 
    Portal portal = new Portal(); 
    Object list = portal.getClass().getDeclaredMethod("getActionList", null).invoke(portal, null); 
    Object action = list.getClass().getDeclaredMethod("get", new Class[] { int.class }).invoke(list, 0); 
    action.getClass().getDeclaredMethod("action", null).invoke(action, null); 
} 

intente ejecutar esto en el mismo paquete que Portal clase y luego una vez más en otra clase fuera del paquete. En el otro paquete, la última línea arrojaría exactamente la misma excepción. Ese es el problema con el que EL está luchando, ya que se basa en la reflexión.

No veo otras maneras de resolver esto bien que simplemente creando un public (interior) class. Reflection (y por lo tanto también EL) puede acceder a ellos desde otros paquetes.

public class Portal { 

    private List<IAction> list = new ArrayList<IAction>(); 

    public Portal() { 
     list.add(new IActionImpl()); 
    } 

    public class IActionImpl implements IAction { 
     public void action() { 
      System.out.println("called action here"); 
     } 
    } 

    public List<IAction> getActionList() { 
     return list; 
    } 

} 
+0

eso es una explicación comprensiva y para este propósito, esta solución funciona bien. gracias ++ – justastefan

+0

De nada. – BalusC

0

La pregunta es bastante viejo, pero me he encontrado hoy el mismo problema, pero sólo porque no tengo cambio de embarcadero 7 a Tomcat 7.

que resolver el problema mediante la sustitución de la biblioteca Jasper EL con el GlassFish Biblioteca EL

+0

Resuelvo el problema también con JUEL el –

Cuestiones relacionadas