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.