Archive for the ‘JSF’ Category

Как легко и непринужденно добавить парваметр в JSF url.

Декабрь 1, 2008

Всё до безобразия просто. Начнем с того, что я опишу задачу, которую мне пришлось решить.

Задача: отобразить список сущьностей с кнопочкой view, при нажатии на которой открывалась бы детальная информация о сущьности.

Зарание извиняюсь за ненормативную лексику, но, как мне кажется, без неё нет возможности показать всю гамму эмоций.

Кажется просто. А хуй там. Ни в одном примере нет нормального описания такого просто Use-Case. Единственно что мне предлагали, так это использовать сессионный бин. Но у этого способа есть свои недостатки. Например нет возможности создать репрезентативный урл, пойдя по которому, ты сразу получишь контент. ПРиходилось сначала идти на страницу с таблицей, а затем, выбрав необходимую сущьность, перходить на интересующую нас «детальку».

Вот тебе бля и «мега Технология» JSF. А хочеться всего ничего, просто написать entity.page?id=1234.

Итак. Задача разбивается на две задачи:

  1. Как обработать параметр на «детальке»
  2. Как установить этот параметр в урле.

Обработать параметр очень просто. Необходимо в faces-config у бина установить managed property примерно вот так (нет особого желания прасписывать что да как).

    <managed-bean>
        <managed-bean-name>customer</managed-bean-name>
        <managed-bean-class>com.ebon.pgw.web.beans.Customer</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
        <managed-property>
            <property-name>customerId</property-name>
            <value>#{param.id}</value>
        </managed-property>
    </managed-bean>

Скажу лишь одно, что param и обозначает параметр передаваемый в запросе.

Вторая задача оказалась по сложнее. Я лишь опишу, как я её решил, сам процесс решения я описывать не буду, дабы не засорять статью табуированной лексикой :).

Помогла мне в решении статья Vladimir Petrukhinа «JSF и ЧПУ (Человеко-понятный урл)«. Именно благодаря ней я узнал, как можно поменять возвращаемый урл. Так как я использовал MyFaces, то мой ViewHandler наследовался от JspViewHandlerImpl. Вот его код.

package test;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.apache.myfaces.application.jsp.JspViewHandlerImpl;
public class GetParamViewHandler extends JspViewHandlerImpl {

    private static final Log log = LogFactory.getLog(GetParamViewHandler.class);

    @Override
    public String getActionURL(FacesContext facesContext, String viewId) {       
        String actionURL = super.getActionURL(facesContext, viewId);
        Map<String, Object> requestParameterMap = FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
        String id = (String) requestParameterMap.get("id");
        if (id!=null) {
            actionURL += "?id=" + id;
            requestParameterMap.remove("id");
        }
        log.info("viewId[%s] actionUrl[%s]", viewId, actionURL);
        return actionURL;
    }
}

Соответсвенно его необходимо прописать в faces-config.xml

<application>
        <view-handler>test.GetParamViewHandler</view-handler>
</application>

Для того, чтобы установить соответсвующий id необходимо использовать f:param примерно так:

<h:commandLink value="view" action="customer" immediate="true">
    <f:setPropertyActionListener value="#{customer.value.merchantId}" target="#{customers.customerId}"/>
    <f:param name="id" value="#{customer.value.merchantId}"/>
</h:commandLink>

Вот наверное и всё. Если у кого есть вопросы и дельные замечания, welcome to comments :)

UPD: Оказалось, что не всё так просто. Во первых, код надо немного переписать (запосчу его позже), во вторых…. А вот про во-вротрых по подробнее.

Описанный выше метод прекрасно работает при простой навигации. А если мне необходимо отредактировать бин. Вот и пришел пиздец. Оказывается, что JSF пытается после нашего клика провести восстановление состояния view (LifeCycle Phase : Restore View), и именно в этот момент у происходит всё заново. А заново не получится, т.к. у нас уже нет в запросе параметра id. Как сделать так, чтобы состояние нормально восстанавливалось я не знаю. Увы :(.