2010-06-08 5 views
6

Je veux avoir un menu générique dans mon application JSF (MyFaces 1.2).Comment appeler l'action JSF sur une classe anonyme? EL ne peut pas y accéder

<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> 

Alors mon portail sur session portée ressemblerait à ceci:

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; 
    } 
} 

Quand je lance ce code, il affiche bien. Mais quand vous essayez d'exécuter l'action en cliquant sur le lien de commande « ClickMe » - l'exception suivante se produira:

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

Est-il possible d'afficher une liste des classes anonymes, dont une méthode (dans cet exemple ITemplate.action()) peut être exécuté?

Edit:

Il fonctionne quand j'utilise une classe (intérieure). Comme par exemple:

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

et dans le constructeur Portal

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

Mais ce n'est pas la façon dont je le veux ...

Répondre

10

C'est parce que les classes anonymes ne sont pas accessibles depuis l'extérieur du boîtier contenant la classe anonyme.

est ici une démonstration ce qui se passe dans les coulisses:

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); 
} 

Essayez d'exécuter ceci dans le même paquet que Portal classe, puis une nouvelle fois dans une autre classe en dehors du package. Dans l'autre paquet, la dernière ligne lancerait exactement la même exception. C'est le problème auquel EL est confronté puisqu'il est basé sur la réflexion.

Je ne vois pas d'autres façons de résoudre cela bien que de simplement créer un public (intérieur) class. La réflexion (et donc EL) peut y accéder à partir d'autres paquets.

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

c'est une explication compréhensible et à cette fin, cette solution fonctionne très bien. merci ++ – justastefan

+0

De rien. – BalusC

0

La question est assez vieux, mais j'ai rencontré le même problème aujourd'hui, mais seulement parce que j'ai passer de Jetty 7 à Tomcat 7.

Je résoudre le problème en remplaçant la bibliothèque Jasper EL avec GlassFish Bibliothèque EL.

+0

Je résous le problème aussi avec JUEL el –

Questions connexes