I am currently working on a project using Primefaces 4.0 and JEE 6. As a build-tool we use maven, and we got a JBoss Application Server.
So it was supposed to be simple. When a validation error occurs, I was supposed to prevent a tab-change in my view. Nothing big, but it needed to be done.
What happened next totally flabberghasted me, but first what I did:
- Define a backing bean to handle the event.
- Define a listener there.
- Use
<p:ajax />
to fire the tabChange event to my bean.
Well it was simple enough until there. When there were no validation errors, it worked just fine. Then I tried to validate the values in the view against my Model-Bean and was quickly stopped in my tracks.
As soon as I willingly produced errors in the View, to trigger the faces messages, the tabChange listener was not executed anymore. In fact, not even the @RequestScoped
controller-class with the listener was constructed.
I proceeded to create a minimal working example with help of the Weld CDI maven archetype.
Now here I stand, at wits end and present to you my example:
home.xhtml:
I removed the surrounding xml-declaration and ui:define stuff, but that's what I took to reproduce it.
<h1>Hello World!</h1>
<p>
Your CDI bean
<code>HelloWorld</code>
says <span style="color: blue;">#{helloWorld.text}</span> using the
Unified EL.
</p>
<h:form id="bv">
<h2>Bean Validation examples</h2>
<p>Enforces annotation-based constraints defined on the model
class.</p>
<p:tabView id="tabView" effect="fade"
effectDuration="normal">
<p:ajax event="tabChange" update="tabView" listener="#{controller.tabChange}"/>
<p:tab title="Tab 1">
<table>
<tr>
<th style="text-align: right;"><h:outputLabel for="letters"
value="Letters:" /></th>
<td><p:inputText id="letters" value="#{helloWorld.letters}" />
<p:message for="letters" errorClass="invalid" /></td>
</tr>
</table>
</p:tab>
<p:tab title="Tab 2">
<p>Random text to be displayed</p>
</p:tab>
</p:tabView>
</h:form>
Controller.java:
here I only removed the package-declaration, for the protection of the innocent.
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
import org.primefaces.event.TabChangeEvent;
@Named
@RequestScoped
public class Controller implements Serializable {
private static final long serialVersionUID = -1126987875831465303L;
public Controller() {
}
@PostConstruct
public void init() {
System.out.println("Constructed " + this.getClass().getSimpleName());
}
public void tabChange(final TabChangeEvent event) {
System.out.println("Listener was reached");
}
}
Last but not least, the model-bean, slightly shortened from what the archetype provides:
HelloWorld.java:
Again I removed the namespace declaration.
import javax.annotation.PostConstruct;
import javax.enterprise.inject.Model;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.NotEmpty;
public @Model
class HelloWorld {
private final String text = "Hello World!";
private String letters;
public HelloWorld() {
}
@PostConstruct
public void initialize() {
System.out
.println(this.getClass().getSimpleName() + " was constructed");
}
public String getText() {
return text;
}
@NotNull
@NotEmpty
@Pattern(regexp = "[A-Za-z]*", message = "must contain only letters")
public String getLetters() {
return letters;
}
public void setLetters(final String letters) {
this.letters = letters;
}
}