Reputation: 893
I'm trying to execute a "helloWorld" project type to learn CDI, and I'm a little lost, I don't understand the behaviour I notice.
Firstly, I tried to execute the examples from the WELD distribution, after having read its reference documentation : http://docs.jboss.org/weld/reference/latest/en-US/html/, Chapter 6
Well, I don't know why, but whatever I try, they do not work for me. So, I decided to "rewrite" the first exercise, and if I can now see the application running (JBoss EAP), I don't understand what's ocurring now :
MY project :
a Generator (ApplicationScoped) which calculate a random number :
@ApplicationScoped
public class Generator implements Serializable{
private static final int MAX_NUMBER = 100;
private java.util.Random random = new java.util.Random(System.currentTimeMillis());
/**
* Serializable
*/
private static final long serialVersionUID = 7388013951586598074L;
@Produces
public @MaxNumber int getMaxNumber(){
return MAX_NUMBER;
}
java.util.Random getRandom() {
return random;
}
@Produces
@Random
int next() {
//a number between 1 and 100
return getRandom().nextInt(MAX_NUMBER - 1) + 1;
}
}
A Game bean, SessionScoped
@SessionScoped
@Named
public class Game implements Serializable{
/**
* Serializable
*/
private static final long serialVersionUID = 8480529461297926872L;
/**
* The real number
*/
private int number;
/**
* The guessed number
*/
private int guess;
/**
* The limit min/max of number could be (updated for each try)
*/
private int biggest;
private int smallest;
/**
* Remaining guesses
*/
private int remainingGuesses;
@Inject
private @MaxNumber int maxNumber;
@Inject
private @Random Instance<Integer> randomNumber;
public void check(){
if (guess > number) {
biggest = guess - 1;
} else if (guess < number) {
smallest = guess + 1;
} else if (guess == number) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!"));
}
remainingGuesses--;
}
@PostConstruct
public void reset(){
this.smallest = 0;
this.guess = 0;
this.remainingGuesses = 10;
this.biggest = maxNumber;
this.number = randomNumber.get();
}
public void validateNumberRange(FacesContext context, UIComponent toValidate, Object value) {
if (remainingGuesses <= 0) {
FacesMessage message = new FacesMessage("No guesses left!");
context.addMessage(toValidate.getClientId(context), message);
((UIInput) toValidate).setValid(false);
return;
}
int input = (Integer) value;
if (input < smallest || input > biggest) {
((UIInput) toValidate).setValid(false);
FacesMessage message = new FacesMessage("Invalid guess");
context.addMessage(toValidate.getClientId(context), message);
}
}
public int getNumber() {
return number;
}
public int getBiggest() {
return biggest;
}
public int getSmallest() {
return smallest;
}
public int getRemainingGuesses() {
return remainingGuesses;
}
public void setRemainingGuesses(int remainingGuesses) {
this.remainingGuesses = remainingGuesses;
}
public int getGuess() {
return guess;
}
public void setGuess(int guess) {
this.guess = guess;
}
}
My two annotations (I put MaxNumber, Random is the same with Random name) :
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE,METHOD,FIELD, PARAMETER})
public @interface MaxNumber {
}
I have my beans.xml, faces-config and web.xml in my WEB-INF folder (nothing else but DOCTYPE, ... in the first 2 files)
and the web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<display-name>Try and guess</display-name>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
And, to conclude, my index.xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<ui:composition template="/template.xhtml">
<ui:define name="content">
<h1>Guess a number...</h1>
<h:form id="numberGuess">
<div style="color: red">
<h:messages id="messages" globalOnly="false" />
<h:outputText id="Higher" value="Higher!"
rendered="#{game.number gt game.guess and game.guess ne 0}" />
<h:outputText id="Lower" value="Lower!"
rendered="#{game.number lt game.guess and game.guess ne 0}" />
</div>
<div>
I'm thinking of a number between <span id="numberGuess:smallest">#{game.smallest}</span>
and <span id="numberGuess:biggest">#{game.biggest}</span>. You have
#{game.remainingGuesses} guesses remaining.
</div>
<div>
Your guess:
<h:inputText id="inputGuess" value="#{game.guess}" required="true"
size="3" disabled="#{game.number eq game.guess}"
validator="#{game.validateNumberRange}" />
<h:commandButton id="guessButton" value="Guess"
action="#{game.check}" disabled="#{game.number eq game.guess}" />
</div>
<div>
<h:commandButton id="restartButton" value="Reset"
action="#{game.reset}" immediate="true" />
</div>
</h:form>
</ui:define>
</ui:composition>
</html>
Well, now, what's occurring :
When I try to access my page, the reset method (marked with PostConstruct) is called several times before index.xhtml is shown. The values shown are the expected one (as it's the first time we access the page) I try to put a number and click on the guess button and, the method reset is called several times (I don't know really why), and my method check (the expected one), one time, to do its job. But then the reset method is called again, and the page shown is in the same state as it was at the beginning. So the question is : - Why the reset method is called more than once at the beginning ? - Why the reset method is called then?
Thanks you Cheloute
Upvotes: 0
Views: 1130
Reputation: 893
Well, I thought that javax.enterprise.context.SessionScoped and javax.faces.bean.SessionScoped were equivalent, but I was wrong :)
I supposed my Game bean was actually with a Dependent scope, as javax.faces.bean.SessionScoped wasn't process as the expected SessionScoped...
Upvotes: 1