0

I have a very strange problem with JSF, but I cannot solve it on my own, because there is no error message I can google for. The problem is, that I have one view for submitting a new article or updating an existing article.

The method getArticle() returns - if ?id=x is set via url - the article POJO with the id of x. Otherwise a pure empty new article. Depending of id is set, the mode editArticle is set to true or false.

So if I pass an id via URL, the form changes to "Update article" and the values of the article are shown. But if I hit the submit button, nothing happens. No output, no error. Using HTTP Live Headers in Firefox, I see a request to the server. Looking with wireshark on the loopback interface, there is traffic, too.

But on the other hand, the "Create new article"-Button (if id is not set) without a problem.

The environment: JSF 2.2, Apache Tomcat 7/8, Java 7/8, Windows/Ubuntu (tried different envs, but always the same, so it seems to be a problem "by design" :-) ). Tried also renaming methods, calling via ActionListener, changing the order of the panelGrids... but no way. The method updateArticle() of the bean is never called by hitting the button.

<h:form id="idMasterForm" enctype="multipart/form-data">
    <h:panelGroup rendered="#{userController.loggedIn}">
            <h:panelGrid columns="2" cellpadding="5">
                <p:outputLabel for="title" value="Title" />
                <p:inputMask id="title"
                    value="#{editArticleController.article.title}" />
                <p:outputLabel for="author" value="Author" />
                <p:inputText id="author" value="#{userController.id}"
                    readonly="true" />
                <p:outputLabel for="date" value="Date" />
                <p:inputMask id="date"
                    value="#{editArticleController.article.date}" readonly="true" />
                <p:outputLabel for="link" value="File" />
                <p:selectOneMenu id="link"
                    value="#{editArticleController.article.link}">
                    <f:selectItems value="#{uploadFilesController.filesItems}" />
                </p:selectOneMenu>
                <p:outputLabel for="editor" value="" />
                <p:editor id="editor" widgetVar="editorWidget"
                    value="#{editArticleController.article.text}" width="600" />
            </h:panelGrid>

            <h:panelGrid columns="2" style="margin-top: 10px" rendered="#{!editArticleController.editArticle}">
                <p:commandButton value="Submit new article"
                    action="#{editArticleController.createArticle()}"
                    icon="ui-icon-disk" />
                <p:commandButton value="Clear" type="button"
                    onclick="PF('editorWidget').clear();" icon="ui-icon-close" />
            </h:panelGrid>

            <h:panelGrid columns="2" style="margin-top: 10px" rendered="#{editArticleController.editArticle}" >
                <p:commandButton value="Update article"
                    action="#{editArticleController.updateArticle()}"
                    icon="ui-icon-disk" />
                <p:commandButton value="Clear" type="button"
                    onclick="PF('editorWidget').clear();" icon="ui-icon-close" />
            </h:panelGrid>
            <h:outputText rendered="#{ ! userController.loggedIn}"
                value="#{res.globNotLoggedIn}" />
    </h:panelGroup>
</h:form>

And here is the Managed Bean:

import java.util.Date;

import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;

import hwr.Util;
import hwr.g2.model.Archive;
import hwr.g2.model.Article;
import hwr.g2.model.Author;
import hwr.user.UserController;

@ManagedBean
public class EditArticleController {
    private Article article;
    private Boolean editArticle;
    private Integer editArticleID;

    public EditArticleController() {
        this.article = new Article();
        System.out.println("EditArticleController was called");
    }

    public Article getArticle() {
        //System.out.println("getArticle() was called");
        if (this.getEditArticle()) {
            this.article = new Article(this.editArticleID);
        }
        return this.article;
    }

    public void setArticle(Integer articleID) {
        this.article = new Article(articleID);
    }

    public void setArticle(Article article) {
        System.out.println("setArticle(Article article) was called");
        this.article = article;
    }

    public void setText(String text) {
        this.article.setText(text);
    }

    public String getText() {
        return this.article.getText();
    }

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

    public String getTitle() {
        return this.article.getTitle();
    }

    public Boolean getEditArticle() {
        // https://stackoverflow.com/questions/550448/get-request-and-session-parameters-and-attributes-from-jsf-pages

        HttpServletRequest req = (HttpServletRequest) FacesContext
                .getCurrentInstance().getExternalContext().getRequest();
        try {
            this.editArticleID = Integer.valueOf(req.getParameter("id"));
            if (this.editArticleID > 0) {
                this.setEditArticle(true);
            } else {
                this.setEditArticle(false);
            }
        } catch (Exception e) {
            this.setEditArticle(false);
        }
        return editArticle;
    }

    public void setEditArticle(Boolean editArticle) {
        this.editArticle = editArticle;
    }

    public Date getActualDate() {
        Date d = new Date();
        return d;
    }

    public void rangChanged() {
        // nothing
    }

    public String createArticle() {
        System.out.println("New Article...");
        Util util = new Util();
        UserController user = (UserController) util.getBean("userController");

        this.article.setAuthor(new Author(user.getId()));
        this.article.setDate(new Date());

        try {
            Archive archive = new Archive();
            archive.addArticle(this.article);
        } catch (Exception e) {
            System.out.println("something goes wrong here...");
            e.printStackTrace();
        }
        return "g2_home?faces-redirect=true";
    }

    public String updateArticle() {
        System.out.println("*** Update Article... ***");

        System.out.println("Debug: Update article, ID "
                + this.article.getId() + "! title: " + this.article.getTitle()
                + " and text: " + this.article.getText()
                + " and written by "
                + this.article.getAuthor().getFirst());

        try {
            Archive archive = new Archive();
            archive.updateArticle(this.article);
        } catch (Exception e) {
            System.out.println("something goes wrong here...");
            e.printStackTrace();
        }
        return "g2_home?faces-redirect=true";

    }
}

I used a checklist of BalusC (action method is not called in JSF), but didn't found something. It whould be really great, if someone can point me in the right direction. By the way, is there an better way to fill the form? In my kind of way, the method getArticle() is called several times by the view.

Community
  • 1
  • 1
xentity
  • 129
  • 1
  • 2
  • 10
  • Kudos @BalusC! I removed the two buttons and replaced them by a "save article" button without 'rendered'. The called function calls createArticle() or updateArticle() depending from the state of editArticle. So is the conclusion: never put a action button with rendered in a form and keep getter very simple? – xentity Dec 29 '14 at 21:24

2 Answers2

1

I Think you should define the managed bean scope @ViewScoped or any other scope you want . look at this question [question] : What is the default Managed Bean Scope in a JSF 2 application?

Community
  • 1
  • 1
Ahmed
  • 131
  • 1
  • 2
  • 6
  • Hi, thanks for reply @Ahmed. I tried it, but it makes no difference. Not even the loader spinner of the browser tab appears... Simply nothing happens in the browser. In the console I see setTitle() of class Article is called with the updated title and UploadFilesController is also called, but not the debug output of updateArticle(). – xentity Dec 28 '14 at 17:39
0

If you don't set the scope for the bean, it will be @RequestScoped by default, which means the bean will be re created per user request. Change it to @ViewScoped at least in order for the bean to keep alive while the user is interacting with the same view in multiple requests (e.g. ajax requests).

@ManagedBean
@ViewScoped
public class EditArticleController {
    //rest of class definition
}
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • Hi, thanks for reply, too. As I wrote above a minute ago: I tried it, but it makes no difference. Not even the loader spinner of the browser tab appears... Simply nothing happens in the browser. In the console I see setTitle() of class Article is called with the updated title and UploadFilesController is also called, but not the debug output of updateArticle(). – xentity Dec 28 '14 at 17:41