Now I have worked a little with JSF, and will like to hear about from someone who can actually give a good reason that I should spend more 5min on this framework.
As a simple case examples, I have created a quiz. It requires user input, data persistence between requests (session), and error messages. While I have added something localization.
To show my quiz there must be a good set of code. The code base itself as to which variable is to put in a backing bean to be stored in request or session. It requires a lot of silly tests on a string result.
But let's look at some code. To demonstrate:
Code:
<f:view>
<f:loadBundle var="locale" basename="website.resources.Locali
zation" />
<h:form id="quiz">
<div>
<p>
<strong>
Question <h:outputText value="#{Quiz.questionIndex + 1}" /> /
<h:outputText value="#{Quiz.numQuestions}" />
</strong>
</p>
<h:outputText
styleClass="error"
rendered="#{Quiz.response == 'failure' && Quiz.allowingTries}"
value="#{locale['Quiz.WrongA
nswer']}" />
<h:outputText
styleClass="error"
rendered="#{!Quiz.allowingTries}&
quot;
value="To Many Attemps (Max 3)" />
<h:outputText
styleClass="approved"
rendered="#{Quiz.response == 'complete'}"
value="#{locale['Quiz.Comple
ted']}" />
<h:panelGroup rendered="#{Quiz.response != 'complete' && Quiz.allowingTries}">
<p>
<h:outputText value="#{Quiz.question}" /> =
<h:inputText styleClass="field" value="#{Quiz.answer}" />
</p>
<p>
<h:commandButton action="#{Quiz.answerQuestion}&quo
t; value="Answer" />
</p>
</h:panelGroup>
</div>
</h:form>
</f:view>
Like so additionally requires a class behind, but a lot of unnecessary code because of the java bean model.
Code:
package website.quiz;
import java.util.*;
public class Quiz
{
private final int MAX_TRIES = 3;
private List<QuizQuestion> questions = new ArrayList<QuizQuestion>();
private int questionIndex = 0;
private QuizQuestion currentQuestion;
private String answer;
private String response;
private int numTries;
private boolean canTry = true;
public Quiz()
{
questions.add(new QuizQuestion("2 + 2","4"));
questions.add(new QuizQuestion("2 - 2","0"));
questions.add(new QuizQuestion("2 * 2","4"));
questions.add(new QuizQuestion("2 / 2","1"));
questions.add(new QuizQuestion("2^2","4&qu
ot;));
currentQuestion = questions.get(questionIndex);
}
public boolean isAllowingTries()
{
return canTry;
}
public void setAllowingTries(boolean canTry)
{
// read only
}
public String getResponse()
{
return response;
}
public void setResponse(String response)
{
// read only
}
public QuizQuestion getQuestion()
{
return currentQuestion;
}
public void setQuestion(QuizQuestion question)
{
// read only
}
public String getAnswer()
{
// always return blank
return "";
}
public void setAnswer(String answer)
{
this.answer = answer;
}
public int getQuestionIndex()
{
return questionIndex;
}
public void setQuestionIndex(int questionIndex)
{
// read only
}
public int getNumQuestions()
{
return questions.size();
}
public void setNumQuestions(int size)
{
// read only
}
public String answerQuestion()
{
if(numTries == MAX_TRIES)
{
canTry = false;
return "continue";
}
if(currentQuestion.getAnswer().equalsIgnor
eCase(answer))
{
if(questionIndex == (questions.size() - 1))
{
response = "complete";
return response;
}
currentQuestion = questions.get(++questionIndex);
response = "continue";
return response;
}
else
{
numTries++;
response = "failure";
return response;
}
}
}
And here comes the navigation rules in faces-config. So xml ending up being handwritten.
Code:
<navigation-rule>
<from-view-id>quiz.jsf</from-view
-id>
<navigation-case>
<from-action>#{Quiz.answerQuestion}
</from-action>
<from-outcome>failure</from-outc
ome>
<to-view-id>quiz.jsp</to-view-id
>
<redirect />
</navigation-case>
<navigation-case>
<from-action>#{Quiz.answerQuestion}
</from-action>
<from-outcome>continue</from-out
come>
<to-view-id>quiz.jsp</to-view-id
>
<redirect />
</navigation-case>
<navigation-case>
<from-action>#{Quiz.answerQuestion}
</from-action>
<from-outcome>complete</from-out
come>
<to-view-id>quiz.jsp</to-view-id
>
<redirect />
</navigation-case>
</navigation-rule>
If I go for example. Will update my JSF with a new kind of response. should I
- Update my Backing Bean with getters and Setters for all the possible variables that are needed to determine what is displayed in the View.
- Update my front end (JSP / JSF / HTML) with some not particularly flexible tags, which additionally requires that there are actually built into the logic of View (which is reasonable conflicting with MVC concept)
- Update my faces-config.xml *sigh*
And as I said, then made up much of the standing of Strings which tosses back and forth, so the possibility of strong types and refractoring are virtually non-existent.
In PHP or ASP.NET would be created above with half as many lines of code, and that there would be no need to update an XML file folders POST requests back and forth, as this largely can be automated by a Front Controller, which Zend (PHP) and ASP.NET MVC (ASP.NET) is built.
In addition, it is much simpler to write the rules, and that there is support for GET mapping on a much simpler way.
To finish with, it can also be said that the server must be restarted for each small change, and such. Tomcat (which I use) does not have virtual directory options, so if I change a CSS value in Eclipse, I * still * residual server and recompile everything.
Overall, it seems incredibly stupid, not very developer friendly, and has no features as PHP or ASP.NET does not have.
We talked about Refractoring in another thread on the topic, but I can only see that there is LESS refractoring in this one in ASP.NET because everything is a string-based compared with Managed Beans, etc.
It is virtually impossible to make anything that involved user input without having to change the faces-config. While I certainly do not think my little pills by Web.config in ASP.NET or zend_config in PHP.
So if there is anyone who has some good knowledge for making it worthwhile even to learn the technology so that themselves.
Being able to support it is not an argument I am much interested in. So I could just as well use my time to learn Cobol.
Bookmarks