Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> JSF/HtmlCommandLink - программно установить action 
:(
    Опции темы
Dims
Дата 3.6.2008, 20:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: нет
Всего: 11



У меня в задаче есть "категории", к каждой категории принадлежат "статьи". 

У меня есть главная страница, на которой я вывожу список категорий. Каждая категория представляет собой ссылку. Все ссылки должны вести на вторую страницу, на которой должен выводиться список статей выбранной категории.

Для обеспечения этого, на главной странице я программно формирую HtmlPanelGrid и заполняю его объектами HtmlCommandLink.

Каждый HtmlCommandLink, по моему представлению, должен сделать две вещи:

1) запомнить выбранную категорию в бине
2) вернуть системе JSF строку, которая указывает перемещение между страницами.

Вот так у меня описано правило перехода:

Код

<navigation-rule>
      <from-view-id>/content.jsp</from-view-id>
      <navigation-case>
         <from-outcome>select</from-outcome>
         <to-view-id>/categ.jsp</to-view-id>
      </navigation-case>
      <navigation-case>
         <from-outcome>edit</from-outcome>
         <to-view-id>/admin/editContent.jsp</to-view-id>
      </navigation-case>
   </navigation-rule>


Вот так я пытаюсь оформить код:

Код

   private void fillCategsPanel() {

      if (categsPanel != null) {
         categsPanel.getChildren().clear();
         if (categs != null && categs.size() > 0) {
            Application application = FacesContext.getCurrentInstance().getApplication();
            HtmlCommandLink link;

            for (final Categ herecateg : categs) {
               link = (HtmlCommandLink) application.createComponent(HtmlCommandLink.COMPONENT_TYPE);
               link.addActionListener(new ActionListener() {

                  public void processAction(ActionEvent arg0) throws AbortProcessingException {
                     try {
                        setCateg(herecateg);
                     } catch (SQLException ex) {
                        Logger.getLogger(SiteController.class.getName()).log(Level.SEVERE, null, ex);
                        throw new AbortProcessingException();
                     }
                  }
               });
               link.setValue(herecateg.getSeq()); 
               link.setActionExpression(application.getExpressionFactory().createMethodExpression(FacesContext.getCurrentInstance().getELContext(), "select", String.class, new Class[0]));
               link.setId("linkto" + herecateg.getSeq());
               categsPanel.getChildren().add(link);
            }
         }
      }
   }


Страница с категориями показывается нормально, но при нажатии ссылки возникает исключение, которое я не понимаю. SiteController -- это бин, который следит за перемещениями по сайту.

type Exception report

message

description The server encountered an internal error () that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: com.telesmi.SiteController$1
    javax.faces.webapp.FacesServlet.service(FacesServlet.java:256)
    org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:390)

root cause

java.lang.IllegalStateException: com.telesmi.SiteController$1
    javax.faces.component.StateHolderSaver.restore(StateHolderSaver.java:98)
    javax.faces.component.UIComponentBase.restoreAttachedState(UIComponentBase.java:1406)
    javax.faces.component.UIComponentBase.restoreState(UIComponentBase.java:1272)
    javax.faces.component.UICommand.restoreState(UICommand.java:332)
    javax.faces.component.html.HtmlCommandLink.restoreState(HtmlCommandLink.java:876)
    javax.faces.component.UIComponentBase.processRestoreState(UIComponentBase.java:1141)
    javax.faces.component.UIComponentBase.processRestoreState(UIComponentBase.java:1157)
    javax.faces.component.UIComponentBase.processRestoreState(UIComponentBase.java:1157)
    javax.faces.component.UIComponentBase.processRestoreState(UIComponentBase.java:1157)
    com.sun.faces.application.StateManagerImpl.restoreState(StateManagerImpl.java:581)
    com.sun.faces.application.StateManagerImpl.restoreView(StateManagerImpl.java:89)
    com.sun.faces.application.ViewHandlerImpl.restoreView(ViewHandlerImpl.java:290)
    com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:141)
    com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:251)
    com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117)
    javax.faces.webapp.FacesServlet.service(FacesServlet.java:244)
    org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:390)

PM MAIL   Вверх
v2v
Дата 3.6.2008, 23:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1620
Регистрация: 20.9.2006
Где: Киев

Репутация: 9
Всего: 56



покажи код jsp страницы, где это происходит.


--------------------
PM   Вверх
Dims
Дата 3.6.2008, 23:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: нет
Всего: 11



Вот код:

Код

         <h:form id="contentForm">
            <%--
            <h:commandLink id="testLink" action="select" value="TESTLINK" actionListener="#{controller.debugEvent}"/>
            --%>

            <h:panelGrid id="categsPanel" binding="#{controller.categsPanel}" columns="20" border="1" cellspacing="0"/>
         </h:form>


PM MAIL   Вверх
v2v
Дата 4.6.2008, 12:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1620
Регистрация: 20.9.2006
Где: Киев

Репутация: 9
Всего: 56



Цитата(Dims @  3.6.2008,  23:19 Найти цитируемый пост)
 <h:commandLink id="testLink" action="select"

замени на 
Код

<h:commandLink id="testLink" action="#{controller.select}"

а в функции возвращай строку "select".


--------------------
PM   Вверх
Dims
Дата 4.6.2008, 23:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: нет
Всего: 11



Так не получится. У меня каждая ссылка -- это категория. Она должна как-то передавать выбранную категорию на следующую страницу. Для этого надо как-то запомнить в бине эту категорию, а команда action="#{controller.select}" этого не обеспечивает.

Поэтому я динамически, в программе, присобачиваю к каждой ссылке свой обработчик. Но вот как правильно сделать action -- не пойму.

Пример, который ты исправил --  закомментирован и не используется. Это я пробовал, работают ли вообще переходы.
PM MAIL   Вверх
ivg
Дата 5.6.2008, 12:58 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Autonomous R&D
**


Профиль
Группа: Участник
Сообщений: 686
Регистрация: 8.2.2006
Где: Екатеринбург

Репутация: 32
Всего: 81



Цитата(Dims @  3.6.2008,  23:47 Найти цитируемый пост)
но при нажатии ссылки возникает исключение, которое я не понимаю

JSF по окончании обработки запроса сохраняет состояние View, а в начале обработки следующего восстанавливает его. Под View в данном случае понимается дерево JSF компонентов расположенных на странице. Для обеспечения этой функциональности каждый компонент реализует интерфейс javax.faces.component.StateHolder, а точнее реализован он в базовом классе, а в классах компонентов переопределяются его методы saveState() и restoreState(). Код этих методов определяет набор полей достаточных для сохранения и восстановления состояния компонента. В этот набор входит список слушателей (Listeners), а вызов HtmlCommandLink.addActionListener() пополняет этот список. Для успешного сохранения и восстановления состояния компонента каждый такой Listener должен "имплементировать" либо StateHolder интерфейс, либо Serializable (подробнее: спецификация JSF, "State Management"). Для превращения объектов, хранящих информацию о состоянии компонента, в последовательность байт используется сериализация. Для анонимного класса определённого внутри метода сериализация "весьма не рекомендуется", если вообще возможна, ибо потянет за собой не только объект бина SiteController, но и потребует сериализовать фрэйм локальных переменных метода.
Вариантов решения ситуации много. Во первых предлагаю избавиться от динамического формирования списка категорий в коде. Для этого можно использовать итерационный тег на странице, например <c:forEach var="cat" items="#{controller.categs}" ... >. А во вторых, что касается передачи значения выбранной категории, то например использовать обычные ссылки в виде:
Код

<h:outputLink ... value="categ.jsp?id=#{cat.id}">#{cat.name}</h:outputLink>

либо
Код

<h:commandLink id="cat_#{cat.id}" value="#{cat.name}" action="select" actionListener="#{controller.getCategory}" />

а в методе getCategory() получаете ID категории:
Код

public void getCategory(ActionEvent event) {
  String idstr = (String) event.getComponent().getId();
  Long id = Long.valueOf(idstr.substring(idstr.lastIndexOf("_")+1));    
  ...
}

Если формирование списка категорий в коде - условие неизменное то код аналогичный
Код

<h:commandLink actionListener="#{controller.getCategory}" />

выглядит так
Код

private void fillCategsPanel() {
  ...
  FacesContext fctx = FacesContext.getCurrentInstance();
  javax.faces.application.Application app = fctx.getApplication();
  ELContext elctx = fctx.getELContext();
  ...
    MethodExpression me = app.getExpressionFactory().createMethodExpression(elctx,
      "#{controller.getCategory}", null, new Class[]{ActionEvent.class});
    link.addActionListener(new MethodExpressionActionListener(me));
  ...
}

Ну и в конце концов можно сделать как вы хотели, только создать отдельный класс, который implements ActionListener, Serializable, в конструктор его передавать категорию, а лучше ID, в методе processAction() достаете из сессии объект бина SiteController и устанавливаете у него выбранную категорию.
Следует заметить, что явно прописывать в коде имя бина, которое является настраиваемым параметром, - не есть хорошо. 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.0581 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.