Выполнение ActionListener пункта меню (Primefaces) приводит к IllegalStateException
в JSF backed bean я получил IllegalStateException
при вызове программно добавленного прослушивателя действий программно добавленного элемента меню Primefaces. Я попробовал оба request
и session
область, но оба приводят к одной и той же ошибке. Очевидно, что необходимо-согласно трассировке стека-восстановить представление, когда выполняется прослушиватель действий, и я позволяю моему ToolbarBean
реализовать Serializable
без другой эффект. Что я должен рассмотреть, чтобы получить это работа?
определение пользовательского интерфейса
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.prime.com.tr/ui">
<h:head>
<title>TITLE</title>
</h:head>
<h:body>
<h:form>
<p:menu model="#{toolbarBean.model}" type="tiered" />
</h:form>
</h:body>
</html>
Backed bean, предоставляющий меню
@Named
@Scope("request")
public class ToolbarBean implements Serializable {
private static final long serialVersionUID = -8556751897482662530L;
public ToolbarBean() {
model = new DefaultMenuModel();
MenuItem item;
// Direct menu item
item = new MenuItem();
item.setValue("Menuitem 1");
item.addActionListener(new ActionListener() {
@Override
public void processAction(ActionEvent event)
throws AbortProcessingException {
System.out.println(event.toString());
}
});
model.addMenuItem(item);
item = new MenuItem();
item.setValue("Menuitem 2");
item.addActionListener(new ActionListener() {
@Override
public void processAction(ActionEvent event)
throws AbortProcessingException {
System.out.println(event.toString());
}
});
model.addMenuItem(item);
}
private MenuModel model;
public MenuModel getModel() {
return model;
}
}
исключение при нажатии одной из кнопок меню
javax.faces.FacesException: java.lang.IllegalStateException: java.lang.InstantiationException: id.co.sofcograha.baseui.ToolbarBean
at javax.faces.component.UIComponent.invokeOnComponent(UIComponent.java:1284)
at javax.faces.component.UIComponentBase.invokeOnComponent(UIComponentBase.java:673)
at javax.faces.component.UIComponent.invokeOnComponent(UIComponent.java:1290)
at javax.faces.component.UIComponentBase.invokeOnComponent(UIComponentBase.java:673)
at javax.faces.component.UIComponent.invokeOnComponent(UIComponent.java:1290)
at javax.faces.component.UIComponentBase.invokeOnComponent(UIComponentBase.java:673)
at javax.faces.component.UIComponent.invokeOnComponent(UIComponent.java:1290)
at javax.faces.component.UIComponentBase.invokeOnComponent(UIComponentBase.java:673)
at com.sun.faces.application.view.StateManagementStrategyImpl.restoreView(StateManagementStrategyImpl.java:297)
at com.sun.faces.application.StateManagerImpl.restoreView(StateManagerImpl.java:177)
at com.sun.faces.application.view.ViewHandlingStrategy.restoreView(ViewHandlingStrategy.java:119)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(FaceletViewHandlingStrategy.java:438)
at com.sun.faces.application.view.MultiViewHandler.restoreView(MultiViewHandler.java:144)
at javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:284)
at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:182)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:97)
at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:107)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:114)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:308)
2 ответов
EL (read: reflection) не может получить доступ/построить анонимные классы. Рефакторинг их в fullworthy классов.
Так, замените
item.addActionListener(new ActionListener() {
@Override
public void processAction(ActionEvent event)
throws AbortProcessingException {
System.out.println(event.toString());
}
});
by
item.addActionListener(new FooActionListener());
и
public class FooActionListener implements ActionListener {
@Override
public void processAction(ActionEvent event)
throws AbortProcessingException {
System.out.println(event.toString());
}
}
Читайте также:
похоже, что дополнительное ограничение заключается в том, что класс ActionListener не имеет аргументов contructor, что добавляет оскорбление к травме здесь. Насколько я вижу, addActionListener, вероятно, просто хранит имя класса переданного ему объекта.
на самом деле, если целью было сделать этот прослушиватель непригодным для использования, предотвращая передачу каких-либо данных слушателю от вашего резервного компонента, они вряд ли могли бы сделать больше.
вы получаете еще одно исключение IllegalStateException если вы попробуете подкласс MenuItem.
вы не можете передать объект, содержащий данные в MenuItem в качестве значения, для этого требуется строка.
Это, похоже, не позволяет слушателю как внутреннему классу.
но я думаю, что я, возможно, взломал его, поместив необходимые данные в карту атрибутов элемента меню.
вот что я закончил:
public class MenuSelectListener implements ActionListener {
public static final String MENU_ACTION_KEY = "menu.action.delegate";
private final static Log log = LogFactory.getLog(MenuSelectListener.class);
@Override
public void processAction(ActionEvent ae) throws AbortProcessingException {
System.out.println("listener invoked");
if (ae.getComponent() instanceof MenuItem) {
Runnable delegate = (Runnable) ae.getComponent().getAttributes().get(MENU_ACTION_KEY);
if(delegate != null)
delegate.run();
else
log.error("Menu action has no runnable");
} else {
log.error("Listener, wrong component class: " + ae.getComponent().getClass().getName());
}
}
}
создать элемент:-
item.setValue("Cancel");
sm.getChildren().add(item);
item.addActionListener(new MenuSelectListener());
item.getAttributes().put(MenuSelectListener.MENU_ACTION_KEY, new MiscActionDelegate(MiscActions.close));
С:
private class MiscActionDelegate implements Runnable, Serializable {
(работает как внутренний класс, но не может быть анонимным).