I have an Article DTO (Article.java; code excerpts)
public class Article {
private int id;
public Article() {
this.id = 0;
}
public Integer getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
I got a view template for editing the article (edit_article.xhtml; code excerpts):
<h:form id="article_form">
<p:messages id="messages"/>
<h:panelGrid columns="2">
<h:outputText value="" />
<h:inputHidden id="articleId" value="#{hqArticleView.article.id}" converter="javax.faces.Integer" />
</h:panelGrid>
</h:form>
and I have a view backing bean (HqArticleView.java; code excerpts):
@Named("hqArticleView")
@RequestScoped
public class HqArticleView implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private Logger log;
@Inject
private IArticleService articleService;
private Article article;
private List<Article> articles;
private Map<String, String> requestParams;
@PostConstruct
private void init() {
log = LoggerFactory.getLogger(getClass());
requestParams = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
article = new Article();
article.setPublish(true);
if (requestParams.containsKey("id")) {
article.setId(Integer.parseInt(requestParams.get("id")));
article = articleService.getArticle(article);
}
}
public Article getArticle() {
return article;
}
public void setArticle(Article article) {
this.article = article;
}
public List<Article> getArticles() {
articles = articleService.getAll();
Collections.reverse(articles);
return articles;
}
public void save() {
log.debug("save pressed");
}
public void edit(Article article) {
log.debug("edit pressed | id=" + article.getId());
}
public void delete(Article article) {
log.debug("delete pressed | id=" + article.getId());
}
}
The problem is: I try to access the view I'm getting an error: The class Article does not have a writable property 'id'. all other fields from the Article are processed correctly, only the id is a problem. Strange is, when I wrap the id getter and setter of the Article object inside the bean in:
public void setId(int id){
this.article.setId(id);
}
public int getId(){
return this.article.getId();
}
then it works perfectly. what am I missing?
When examing the property type for reading, EL looks at the return type of the getter:
It's thus of type
Integer
. When EL needs to write the changed value, EL is expecting a setter taking the same type:However, no such setter exists in your
Article
class. Instead, you've a setter taking anint
. That's exactly why EL threw aPropertyNotWritableException
. It means that it couldn't find a matching setter taking exactly the same type. Fix it accordingly by usingInteger
instead ofint
in the setter (or, in this particular case better, by usingint
instead ofInteger
in the getter).That it worked when you exploded the model in the controller (bad practice by the way) is because the getter and setter matched each other.