JSF MethodExpression не запускает мое действие поддерживающего бина - PullRequest
2 голосов
/ 20 марта 2009

У меня проблема в том, что мой код не вызывает действие в моем компоненте поддержки. Код выглядит следующим образом:

HtmlCommandButton replyCommentButton = new HtmlCommandButton();
replyCommentButton.setId("replyCommentButton" + commentCounter);
replyCommentButton.setValue("Create reply");
String action = "#{Handler.action_replyToComment}";
MethodExpression methodExpression =  
FacesContext.getCurrentInstance().getApplication().getExpressionFactory().
createMethodExpression(FacesContext.getCurrentInstance().getELContext(), action, null,
new Class<?>[0]);
replyCommentButton.setActionExpression(methodExpression);

В моем компоненте поддержки с именем RequestHandlerBean, определенном в FacesConfig как обработчик, у меня есть следующий код:

public void action_replyToComment() {
logger.info("Homemade action called!!!");
System.out.println("Homemade action called!!!");
}

Кто-нибудь определяет, почему ничего не происходит, когда я нажимаю кнопку? Это не вызывает событие должным образом. Источник HTML-кода выглядит следующим образом:

<input id="replyCommentButton1" type="submit" value="Create reply"   
name="replyCommentButton1"/>

Как мы видим, в HTML не определено никаких действий.

Редактировать 2: Я только что узнал в Javadoc, что мой метод действия должен быть публичной строкой. Я изменил это в своем компоненте поддержки, поэтому код в его компоненте:

public String action_replyToComment() {
logger.info("Homemade action called!!!");
System.out.println("Homemade action called!!!");
return null;
}

Edit2: я также убедился, что он инкапсулирован в теге, но все равно не повезло. Не должен ли быть атрибут действия в элементе?


Edit3: Мой bean-компонент определен в моей конфигурации лиц следующим образом:

<managed-bean>
<description>
Handles the specific request.
</description>
<managed-bean-name>Handler</managed-bean-name>
<managed-bean-class>no.ngt.tech.rt2.beans.RequestHandlerBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>

Также, если я выберу вывод на своей странице JSF, как это:

<a4j:commandButton action="#{Handler.action_replyToComment}" value="Reply" /> 

Это прекрасно работает

РЕДАКТИРОВАТЬ 4 - МОЯ СТРАНИЦА JSP Заметьте, что я также пытался использовать устаревшую setAction (methodBinding) сейчас, но, к сожалению, это тоже не сработало.

<%@ include file="_includes.jsp" %>
<f:view>
<html>
<head>
<title><h:outputText value="#{msgs.title}" /></title>
</head>
<body>
<br /><br /><br />



<%@ include file="_menu.jsp" %>

<rich:tabPanel switchType="client">

<rich:tab id="commentsTab" label="Comments" rendered="#{Handler.editRequest}">
<h:form>
         <ngt:commentTree binding="#{Handler.commentTree}" value="#{Handler.comments}"  />

         <br />

         <a4j:commandButton action="#{Handler.action_replyToComment}" value="testbutton" />
</h:form>    
</rich:tab>


</rich:tabPanel>

</body>
</html>
</f:view>

menu.jsp:

<h:form>
    <rich:toolBar itemSeparator="line" styleClass="toolbar" contentClass="toolbar" height="22">
        <rich:toolBarGroup>
            <rich:menuItem submitMode="server" value="Front" action="#{newRT.action_showFront}" />
        </rich:toolBarGroup>
        <rich:toolBarGroup>
            <rich:menuItem submitMode="server" value="New request" action="#{Step.action_showSteps}" />
        </rich:toolBarGroup>
        <rich:toolBarGroup>
            <rich:menuItem submitMode="server" value="Requests" action="#{Handler.action_showRequestsView}" />
        </rich:toolBarGroup>
        <rich:toolBarGroup>
            <rich:menuItem submitMode="server" value="Control-panel" action="#" />
        </rich:toolBarGroup>
        <rich:toolBarGroup location="right">
            <h:inputText styleClass="barsearch" value="#{Handler.search}" />
            <a4j:commandButton styleClass="barsearchbutton" action="#{Handler.action_GetRequestFromID}"  value="Search" />
        </rich:toolBarGroup>
    </rich:toolBar>
</h:form>


<br/><br/>

Includes.jsp

<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="a4j" uri="http://richfaces.org/a4j" %>
<%@ taglib prefix="rich" uri="http://richfaces.org/rich"%>
<%@ taglib prefix="ngt" uri="http://MySpecialTagLib.no/"%>

Редактировать 7 - Java-код для UIComponent:

Это CommentsTreeUI.java:

public class CommentsTreeUI extends UIOutput {

    private static Logger logger = Logger.getLogger(CommentsTreeUI.class.getName());

    @Override
    public void encodeBegin(FacesContext context) throws IOException {

        List<CommentTag> value = (List<CommentTag>) getAttributes().get("value");
        int commentCounter = 0;

        if (value != null) {
            for (CommentTag comment : value) {
                commentCounter++;
                ResponseWriter commentContainerWriter = context.getResponseWriter();
                commentContainerWriter.startElement("div", this);
                commentContainerWriter.writeAttribute("id", "Comment" + commentCounter, null);

                String width = comment.getWidth();
                String height = comment.getHeight();

                String style = comment.getStyle();

                style = (style != null) ? style + ";" : "";

                if (width != null) {
                    style += "width:" + width + ";";
                }
                if (height != null) {
                    style += "height:" + height + ";";
                }

                commentContainerWriter.writeAttribute("style", style, null);

                String newComment = comment.getNewComment();
                if (newComment == null) {
                    newComment = "false";
                }

                String level = comment.getLevel();

                if (level != null) {
                    level = "commentContainerLevel" + level + newComment;
                }
                commentContainerWriter.writeAttribute("class", level, null);

                String title = comment.getTitle();
                if (title != null) {
                    commentContainerWriter.writeAttribute("title", title, null);
                }

                String titleText = comment.getTitleText();
                if (titleText != null) {
                    ResponseWriter titleTextWriter = context.getResponseWriter();
                    UIOutput titleTextComponent = new UIOutput();
                    titleTextWriter.startElement("div", titleTextComponent);
                    titleTextWriter.writeAttribute("class", "commentHeaderText" + newComment, null);
                    titleTextWriter.writeText(titleText + " | ", null);
                    titleTextWriter.startElement("a", titleTextComponent);
                    titleTextWriter.writeAttribute("onclick", "showCommentReply('CommentReply" + commentCounter + "')", null);
                    titleTextWriter.writeAttribute("class", "reply", null);
                    titleTextWriter.writeText("Reply", null);
                    titleTextWriter.endElement("a"); 
                    titleTextWriter.endElement("div");
                }

                String commentBody = comment.getCommentBody();
                if (commentBody != null) {
                    ResponseWriter commentBodyWriter = context.getResponseWriter();
                    UIOutput commentBodyComponent = new UIOutput();
                    commentBodyWriter.startElement("div", commentBodyComponent);
                    commentBodyWriter.writeText(commentBody, null);
                    commentBodyWriter.endElement("div");
                }

                ResponseWriter replyContainerWriter = context.getResponseWriter();
                UIOutput replyContainerComponent = new UIOutput();
                replyContainerWriter.startElement("div", replyContainerComponent);
                commentContainerWriter.writeAttribute("id", "CommentReply" + commentCounter, null);
                replyContainerWriter.writeAttribute("class", "replyContainer", null);

                ResponseWriter replyHeaderWriter = context.getResponseWriter();
                UIOutput replyHeaderComponent = new UIOutput();
                replyHeaderWriter.startElement("div", replyHeaderComponent);
                replyHeaderWriter.writeAttribute("class", "replyHeaderContainer", null);
                replyHeaderWriter.endElement("div");

                ResponseWriter replyFormWriter = context.getResponseWriter();
                UIInput replyFormComponent = new UIInput();
                replyFormWriter.startElement("fieldset", replyFormComponent);
                replyFormWriter.startElement("textarea", replyFormComponent);
                replyFormWriter.writeAttribute("type", "textarea", null);
                replyFormWriter.writeAttribute("rows", "5", null);
                replyFormWriter.writeAttribute("cols", "76", null);
                replyFormWriter.writeText("Write your answer here", null);
                replyFormWriter.endElement("textarea");


                //TODO: Fix so button has action to backing bean
                HtmlAjaxCommandButton replyCommentButton = new HtmlAjaxCommandButton();
                replyCommentButton.setId("replyCommentButton" + commentCounter);
                replyCommentButton.setValue("Create reply");
                String action = "#{RequestHandlerBean.action_replyToComment}";
                //replyCommentButton.setReRender("commentsTree");
                ExpressionFactory factory = context.getApplication().getExpressionFactory();
                Class [] argtypes=new Class[1];
                argtypes[0]=ActionEvent.class;

                MethodExpression replyActionExpression = factory.createMethodExpression(context.getELContext(), action, null, argtypes);
                replyCommentButton.setActionExpression(replyActionExpression);

                MethodExpression methodExpression = context.getCurrentInstance().getApplication().getExpressionFactory().
                        createMethodExpression(context.getCurrentInstance().getELContext(), action, null, new Class<?>[0]);
                replyCommentButton.setActionExpression(methodExpression);
                /*
                replyCommentButton.setAction(context.getApplication().createMethodBinding(action, argtypes));
                */

                replyCommentButton.encodeAll(context);
                //Todo above


                replyFormWriter.writeText(" ", null);
                replyFormWriter.startElement("input", replyFormComponent);
                replyFormWriter.writeAttribute("type", "button", null);
                replyFormWriter.writeAttribute("value", "Cancel ", null);
                replyFormWriter.writeAttribute("onclick", "hideCommentReply('CommentReply" + commentCounter + "')", title);
                replyFormWriter.endElement("input");
                replyFormWriter.endElement("fieldset");
                replyContainerWriter.endElement("div");
                commentContainerWriter.endElement("div");
            }
        } else { //value==null
            ResponseWriter writer = context.getResponseWriter();
            writer.startElement("div", this);

            writer.writeAttribute("id", getClientId(context), null);

            String width = (String) getAttributes().get("width");
            String height = (String) getAttributes().get("height");

            String style = (String) getAttributes().get("style");

            style = (style != null) ? style + ";" : "";

            if (width != null) {
                style += "width:" + width + ";";
            }
            if (height != null) {
                style += "height:" + height + ";";
            }

            writer.writeAttribute("style", style, null);

            String styleClass = (String) getAttributes().get("styleClass");
            if (styleClass != null) {
                writer.writeAttribute("class", styleClass, null);
            }

            String title = (String) getAttributes().get("title");
            if (title != null) {
                writer.writeAttribute("title", title, null);
            }

        }
    }

    @Override
    public void encodeEnd(FacesContext context) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        writer.endElement("div");
    }

Это CommenstTreeTag:

public class CommentsTreeTag extends UIComponentTag {

    String style;
    String styleClass;
    String title;
    String width;
    String height;
    String value;
    Long parentId;

    public void release() {
        // the super class method should be called
        super.release();
        style = null;
        styleClass = null;
        title = null;
        height = null;
        width = null;
        parentId = null;
        value = null;
    }

    @Override
    protected void setProperties(UIComponent component) {
        // the super class method should be called
        super.setProperties(component);

        if (style != null) {
            component.getAttributes().put("style", style);
        }

        if (styleClass != null) {
            component.getAttributes().put("styleClass", styleClass);
        }

        if (width != null) {
            component.getAttributes().put("width", width);
        }

        if (height != null) {
            component.getAttributes().put("height", height);
        }

        if (title != null) {
            if (isValueReference(title)) {
                ValueBinding vb =
                        getFacesContext().getApplication().createValueBinding(title);
                component.setValueBinding("title", vb);
            } else {
                component.getAttributes().put("title", title);
            }
        }
        if (value != null) {
            if (isValueReference(value)) {
                ValueBinding vb =
                        getFacesContext().getApplication().createValueBinding(value);
                component.setValueBinding("value", vb);
                getFacesContext().getApplication().createValueBinding(value);

            } else {
                component.getAttributes().put("value", value);
            }
        }
        if (parentId != null) {
            component.getAttributes().put("parentId", parentId);
        }
    }



    public String getComponentType() {
        return "commentTree";
    }

    public String getRendererType() {
        // null means the component renders itself
        return null;
    }

    public String getHeight() {
        return height;
    }

    public void setHeight(String height) {
        this.height = height;
    }

    public String getWidth() {
        return width;
    }

    public void setWidth(String width) {
        this.width = width;
    }

    public String getStyle() {
        return style;
    }

    public void setStyle(String style) {
        this.style = style;
    }

    public String getStyleClass() {
        return styleClass;
    }

    public void setStyleClass(String styleClass) {
        this.styleClass = styleClass;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

Ответы [ 2 ]

3 голосов
/ 24 марта 2009

Я думаю, что проблема, с которой вы сталкиваетесь, связана с тем, как вы добавляете commandButton в дерево компонентов JSF, или, точнее, с тем, как вы НЕ добавляете его в дерево компонентов.

Поскольку вы не присоединяете commandButton к дереву компонентов JSF, при визуализации этого компонента (с помощью вашего вызова метода .encodeAll ()) он не находит форму, в которую вложен этот компонент. Таким образом, ввод HTML не создан правильно.

Может быть, вы можете попробовать добавить команду commandButton, созданную непосредственно в форму, перед тем как запросить ее визуализацию. Вы можете сделать это с помощью следующего кода:

// Search for the component HtmlForm that is a (in)direct parent of the current component
private UIComponent getCurrentForm(UIComponent currentComponent) {
    UIComponent parent = currentComponent.getParent();
    while ((parent != null) && !(parent instanceof HtmlForm)) {
        parent = parent.getParent();
    }
    return parent;
}


public void encodeBegin(FacesContext context) throws IOException {
    ...
    HtmlAjaxCommandButton replyCommentButton = new HtmlAjaxCommandButton();
    ...

    // Add the command button in the form that contains your custom component...
    UIComponent form = getCurrentForm(this);
    if (form != null) {
        form.getChildren().add(replyCommentButton);
    }
    replyCommentButton.encodeAll(context);
    ...
}

обратите внимание, что я тестировал этот код, поэтому, возможно, вам придется немного его изменить ...

Если это все еще не работает, возможно, вам нужно будет пересмотреть свой код, чтобы создать commandButton вне класса рендеринга или вне encodeBegin ... Я не думаю, что это хорошая идея, чтобы изменить JSF дерево компонентов на этапе рендеринга ...

1 голос
/ 20 марта 2009

Ваш код кажется правильным (действительно, метод должен возвращать String, но он также может возвращать void, даже если ему не рекомендуется писать такой метод действия).

Вы уверены, что созданная commandButton вложена в компонент? Иначе это не сработает. Под этим я подразумеваю, что (созданный на странице Java или JSF, независимо от), должен иметь прямого или косвенного родительского (в дереве компонентов JSF) компонента. Например:

<h:form>
  ...
  <h:commandButton .../>
  ...
</h:form>

Есть ли у вас ошибка Javascript, когда вы нажимаете на проблему?

Редактировать относительно комментария.

Edit 2, относительно моего комментария к основному сообщению:

Может быть, вы можете попытаться прикрепить действие к вашей кнопке старым способом (хорошо, это устарело, но просто попробуйте):

replyCommandButton.setAction(context.getApplication().createMethodBinding("#{Handler.action_replyToComment}", null));
...