mboost-dp1

JSF / Java EE - Hvorfor


Gå til bund
Gravatar #101 - arne_v
12. maj 2009 17:36
#97

Det er muligt at det overraskede nogle folk, men det burde det ikke.

Og det er ikke en restriktion på method overload, men en konsekvens af type erasure i java generics.

Du kan ikke have to metode med samme signatur.
Gravatar #102 - myplacedk
12. maj 2009 17:36
Windcape (98) skrev:
En system.out.printf version der automatisk tilføjer \n ville da være dejligt ;)

Normalt bruger man kun System.out ca. ét sted i et program. Hvis du gerne vil have en printf der automatisk tilføjer et linjeskift, så brug de 3 sekunder det tager at lave på noget mere fornuftigt end at brokke dig.
Gravatar #103 - Windcape
12. maj 2009 17:40
arne_v (101) skrev:
Og det er ikke en restriktion på method overload, men en konsekvens af type erasure i java generics.
Ja, men hvor mange udviklerer er det lige som har et godt kendskab til type erasure?

Jeg synes netop at type erasure virker som et meget grundlæggende problem for at udvide syntaksen i Java, hvorfor så mange ting bliver lavet med annotations i form af hvad der ellers ville være code comments, eller i xml.

Og er det ikke den bedste løsning? At designe flexible sprog som kan udvides til nye formål nemt ? Det kan da kun gøre chefen glad!
Gravatar #104 - myplacedk
12. maj 2009 17:41
Windcape (100) skrev:
Det er noget ret almens.

Det er almindeligt at have sådan nogle metoder, men det er ikke almindeligt at bruge sin hverdag på at implementere dem. Vi overlever ganske fint.
Gravatar #105 - Windcape
12. maj 2009 17:42
Det er slet ikke alm. at bruge sin hverdag på at kode (Men mere design, diskussion og dokumentation). Det ændre dog ikke på problemet.

Fordi så kunne vi jo , som sagt, ligeså godt blive ved med at kode alting i COBOL.

(Medmindre man arbejdet med webudvikling, de bruger vist ret meget tid på at kode :p)
Gravatar #106 - myplacedk
12. maj 2009 17:45
#105
For programmører er det. Og vi andre har også perioder hvor hverdagen går med at kode. Alligevel er det sjældent jeg laver equals-metoder.

At skifte til COBOL ville drastisk ændre min hverdag. At kunne lave equals-metoder som du gerne vil, ville jeg overhovedet ikke tænke over. Og smid alle de andre små-detaljer du ikke kan leve uden med oveni, og det vil stadig være det samme.
Gravatar #107 - arne_v
12. maj 2009 17:46
#98

Tja.

Java valgte altså C modellen, så du skal bruge:

System.out.printf("%s %s%n", foo, bar);
Gravatar #108 - Windcape
12. maj 2009 17:49
C modellen er også fin, jeg ville bare gerne at den også selv tilføjede \n :-)

Det er en ideel måde at håndtere output til console applications synes jeg.

myplacedk (106) skrev:
Alligevel er det sjældent jeg laver equals-metoder.
Jeg går ud fra du ikke arbejder særlig meget med NHibernate så?

Grunden til jeg netup ville implementere et type-safe abstract class (som type easures ikke tillader), var fordi at som udvikler ender man tit med at lave dovne løsninger.


equals(Object obj)
{
return ((Foo)obj).getBar() == this.bar;
}


Overstående 3 linjer har utrolig mange fejl i.
Gravatar #109 - arne_v
12. maj 2009 17:53
Windcape (103) skrev:
Ja, men hvor mange udviklerer er det lige som har et godt kendskab til type erasure?


Ikke så mange som der burde være. Det giver notorisk problemer.

Windcape (103) skrev:
Jeg synes netop at type erasure virker som et meget grundlæggende problem for at udvide syntaksen i Java,


Type erasure er ikke valgt udfra tekniske årsager men af kompabilitets hensyn.

Windcape (103) skrev:
hvorfor så mange ting bliver lavet med annotations i form af hvad der ellers ville være code comments, eller i xml.


Det er jo en feature Java har arvet fra C# !

:-)
Gravatar #110 - arne_v
12. maj 2009 17:56
myplacedk (104) skrev:
Det er almindeligt at have sådan nogle metoder, men det er ikke almindeligt at bruge sin hverdag på at implementere dem. Vi overlever ganske fint.


Og ellers kan ens IDE formentlig generere dem.

Eclipse kan.
Gravatar #111 - Windcape
12. maj 2009 17:56
arne_v (109) skrev:
Det er jo en feature Java har arvet fra C# !
Jeg vil så sige, at jeg ikke kan lide implementationen ;)

Men det er en meget effiktiv teknologi. Specielt til f.eks. webudvikling


[GET]
ActionResult AddComment()
{
}

[POST]
ActionResult AddComment(string name, string comment)
{
}


Ihvertfald noget pænere end en if(HttpContext.RequestType == RequestType.POST) { return; } i hver metode.
Gravatar #112 - Windcape
12. maj 2009 17:57
arne_v (110) skrev:
Og ellers kan ens IDE formentlig generere dem.

Eclipse kan.
Med både null og type check?

Den generere kun en dummy metode for mig, som har fejlene fra #108
Gravatar #113 - arne_v
12. maj 2009 17:58
Windcape (105) skrev:
Fordi så kunne vi jo , som sagt, ligeså godt blive ved med at kode alting i COBOL.


Udviklingen i programmerings sprog drejer sig ikke så meget om at undgå at skrive kode som om at skrive kode der har færre fejl og er nemmere at læse.
Gravatar #114 - Windcape
12. maj 2009 17:59
Jeg synes de 2 ting har det med at følges ad. LINQ er ihvertfald et godt eksempel på det.
Gravatar #115 - arne_v
12. maj 2009 18:07
Windcape (112) skrev:
Med både null og type check?


Ja.

Testet med både 3.3 og 3.4.
Gravatar #116 - myplacedk
12. maj 2009 18:07
Windcape (108) skrev:

equals(Object obj)
{
return ((Foo)obj).getBar() == this.bar;
}


Overstående 3 linjer har utrolig mange fejl i.

Det kommer helt an på dine preconditions. Jeg har lavet masser af fejlfri kode, med de "fejl" i.
Gravatar #117 - arne_v
12. maj 2009 18:08
Windcape (111) skrev:
Jeg vil så sige, at jeg ikke kan lide implementationen ;)


Den er ellers også stort set den samme som i .NET !
Gravatar #118 - arne_v
12. maj 2009 18:09
Windcape (111) skrev:
Ihvertfald noget pænere end en if(HttpContext.RequestType == RequestType.POST) { return; } i hver metode.


Hvis koden ser sådan ud så er der nok noget galt.

Men det har næppe noget med Java annotations at gøre.
Gravatar #119 - Windcape
12. maj 2009 18:23
arne_v (118) skrev:
Hvis koden ser sådan ud så er der nok noget galt.

Men det har næppe noget med Java annotations at gøre.
Det var sådan det ville se ud uden type-check annotation.

arne_v (117) skrev:
Den er ellers også stort set den samme som i .NET !
Jeg tænker fra et rent syntaksmæssig synspunkt.

myplacedk (116) skrev:
Det kommer helt an på dine preconditions. Jeg har lavet masser af fejlfri kode, med de "fejl" i.
I de 3 linjer var fejlene:

Intet null check.
Intet type check.
Der blev sammenlignet en getter med en intern variable. Hvis getteren ændre på værdien, ville sammenligningen være invalid.
Gravatar #120 - paradise_lost
12. maj 2009 18:33
#91 Fair nok at du overvejer din fremtid, men hvis du forventer at folk skal lytte til fornuften i hvad du siger, så er du også nød til at høre fornuften i hvad andre siger og acceptere at der findes andre græsgangne end netop den som du finder rigtig! :)
Gravatar #121 - arne_v
12. maj 2009 18:42
Windcape (119) skrev:
Jeg tænker fra et rent syntaksmæssig synspunkt.


Du synes at [Foobar] er markant bedre end @Foobar ?

:-)
Gravatar #122 - Windcape
12. maj 2009 19:15
Ja, specielt når der skal argumenter med

[Auth(Role="Admin", User="Windcape")]
Gravatar #123 - arne_v
12. maj 2009 19:32
#122

Altså sammenlignet med:

@Auth(role="Admin", user="Windcape")
Gravatar #124 - myplacedk
12. maj 2009 20:02
Windcape (119) skrev:
I de 3 linjer var fejlene:

Intet null check.
Intet type check.
Der blev sammenlignet en getter med en intern variable. Hvis getteren ændre på værdien, ville sammenligningen være invalid.

Okay, jeg havde overset at du tilgik det samme field på to forskellige måder. Det ville jeg ikke have gjort, men det er da vist også bare dårlig kodestil, og ikke emnet for samtalen.

Men ellers kan du jo bare sige at preconditions er at variablen ikke er null, og har den rette type. Den slags preconditions er typisk intet problem. Metoden bliver jo alligevel typisk brugt til at sortere en samling, som i sig selv har samme krav.
Gravatar #126 - arne_v
13. maj 2009 17:37
#125

Jep. Undervisningsministeriets side (www.evaluering.uvm.dk) er lavet i JSF.

Men demo af testen (demo.evaluering.uvm.dk) er lavet i ASP.NET.

Jeg ved ikke helt hvad du vil konkludere udfra det.
Gravatar #127 - Windcape
13. maj 2009 18:18
At konceptet med validerings-controls er elendigt, og kun skaber problemer ligesom dette :)
Gravatar #128 - Windcape
13. maj 2009 18:20
Derudover er siden også et godt eksempel på hvad jeg mener med at JSF har en idiotisk arkitektur.

Se hvordan http://www.evaluering.uvm.dk/ skifter side med POST requests.
Gravatar #129 - arne_v
27. maj 2009 01:45
Windcape (127) skrev:
At konceptet med validerings-controls er elendigt, og kun skaber problemer ligesom dette :)


Jeg ville konkludere at man netop skulle bruge en vel gennem-testet server-side kontrol fremfor noget adhoc validering.

(jeg tillader mig at antage at det ikke er en standard ASP.NET validerings kontrol de har brugt)
Gravatar #130 - arne_v
27. maj 2009 01:47
Windcape (114) skrev:
Jeg synes de 2 ting har det med at følges ad. LINQ er ihvertfald et godt eksempel på det.


Jeg synes, at man ser rigtigt meget ulæselig LINQ kode.

LINQ er nydeligt til meget simple ting.

Men bruger man det til mere komplekse ting, så bliver det hurtigt ulæseligt.
Gravatar #131 - arne_v
27. maj 2009 01:54
Windcape (87) skrev:
Forskellen er bare at extension methods virker som en del af sproget, istedet for et statisk bibliotek. Endnu en fordel til udvidelsen af C#.


Extensions metoder er meget smarte.

Men de er også lidt farlige.

Det er nemlig ikke helt ligetil at finde ud af hvor de kommer fra.

Derfor er det et værktøj som man skal omgåes med en vis forsigtighed. Ellers kan ens kode blive endda aldeles umulig at følge.

De har også været foreslået til Java 7. Men kommer så vidt jeg ved ikke med.

Gravatar #132 - arne_v
27. maj 2009 02:03
Windcape (85) skrev:
Derudover er der jo problemer med bean-modellen. F.eks. JSF kræver at du har både Getters og Setters for at kunne benyttes.

Så får at lave en read-only property skal man definere en blank setter.

public void setFoo() {
// part of read-only property, waste of code, hurrayz!
}


Jeg synes det er idioti på et højt plan, og at det ikke er blevet fixet over en periode på 10 år viser jo bare hvor uddateret Java er som sprog.


Det var jo et framragende argument mod JSF.

Hvis altså det var rigtigt.

Men det er det ikke.

Hvis du vil have en readonly property så undlader du bare at have en set metode.

Det virker fint i JSF.

Det giver sig selv, at hvis du forsøger at sætte propety'en og der ikke er en setter, så får du en fejl.

Endvidere skal man være opmærksom på at man ved initialiseringen i faces-config.xml kun kan benytte setter DI ikke constructor DI.
Gravatar #133 - arne_v
27. maj 2009 02:16
Windcape (83) skrev:
Syntaks er også det vigtigste i et programmerings sprog, da det nu engang er det vi bruger mest tid på!


Det gør det jo ikke godt at have 2 syntaxer for det samme.


Windcape (83) skrev:
Det er .NET også

http://en.wikipedia.org/wiki/Shared_Source_Common_...


Der er Mono, DotGnu og SSCLI - men ingen af dem er MS .NET kompatible.

Fra den wikipedia artikel du linker til:

"Most of the .NET framework class libraries are present except for ADO.NET, Windows Forms, Web Forms, and Web Services. Either you or the Rotor community will have to implement these. On a less painful note, remoting, networking, and XML functionality (and source) are included."


Det kan man vist ikke bruge til ret meget.

Mono er trods alt langt bedre.

Men Mono har også mangler.

Windcape (83) skrev:
Forskellen er at Mono ikke bliver sagsøgt for 20 millioner når de laver nye ting til C# og deres libraries.


SUN sagsøger heller ikke nogen fordi de udvider Java (forudsat at de ikke smider udvidelserne i de samme packages som standarden bruger).

SUN sagsøger alle som laver en Java der mangler noget. MS blev sagsøgt fordi de manglede JNI og RMI.

Kravet for at kunne kalde noget Java er *alt* i standard Java er der. Så man kan være sikker på at ethvert standard Java program kører - eller mere korrekt: ethvert standard Java program ikke mangler klasser eller metoder.

Og der er som sagt en skrap test som skal beståes førend man bliver godkendt som værende en Java.
Gravatar #134 - Windcape
27. maj 2009 10:45
arne_v (132) skrev:
Hvis du vil have en readonly property så undlader du bare at have en set metode.

Det virker fint i JSF.
Ikke for mig. Jeg blev påtvunget at have setters for at mine properties var synlige i View delen.

Det kan også være på IDE basis, men under alle omstændigheder, ikke noget jeg finder specielt positivt.

arne_v (133) skrev:
Og der er som sagt en skrap test som skal beståes førend man bliver godkendt som værende en Java.
Så skrap at der ikke lader til at være nogle som gider forsøge sig med det mere.

Og JNI er ret svag i forhold til P/Invoke, og RMI er ikke noget jeg synes er specielt brugbart.

Hvor genialt er det at kræve "throws RemoteException" på hver eneste metode til stub-interfaces. Det kan self. være pga. java's måde at håndterer exceptions på, men det er også super grimt kode.
Gravatar #135 - arne_v
28. maj 2009 17:44
Windcape (134) skrev:
Ikke for mig. Jeg blev påtvunget at have setters for at mine properties var synlige i View delen.

Det kan også være på IDE basis, men under alle omstændigheder, ikke noget jeg finder specielt positivt.


Nope. Men det må dig og din IDE jo se om I kan finde ud af.

Windcape (134) skrev:
Så skrap at der ikke lader til at være nogle som gider forsøge sig med det mere


Øh.

Der er da mange som får deres Java certificeret.

SUN, IBM, Oracle, OpenJDK, Redhat er alle blevet certificeret for nyeste Java.

Apache er ret vild efter at blive det, men skændes med SUN omkring et licens spørgsmål.

Windcape (134) skrev:
Og JNI er ret svag i forhold til P/Invoke


Det er jeg enig i.

Man valgte med JNI at lægge konverteringen på den native side. Og det var ikke et heldigt valg:
- det kræver specielle .dll/.so/.exe fordi de eksisterende bruger ikke JNBI konvention
- generelt er det betydeligt sværere at kode konverteringen i C end i Java/C#

Windcape (134) skrev:
og RMI er ikke noget jeg synes er specielt brugbart.


Det gør det samme som .NET remoting.

Det er bare lidt nemmere at bruge på nogle områder.

Windcape (134) skrev:
Hvor genialt er det at kræve "throws RemoteException" på hver eneste metode til stub-interfaces. Det kan self. være pga. java's måde at håndterer exceptions på, men det er også super grimt kode.


Du kan kalde det grimt. Men det er jo virkeligheden. Remote kald er ikke transparente. Der er altid mulighed for at få en netværks fejl. RemoteException minder client apps om den lille detalje.
Gravatar #136 - arne_v
4. jun. 2009 02:12
#0

Jeg brugte lige lidt tid til at gå tilbage til udgangspunktet.

Og som sagt, så er består ret meget af det overstående af Strings der tosses frem og tilbage, så muligheden for stærke typer og refractoring er stort set ikke eksisterende.


Vi snakkede om Refractoring i en anden tråd om emnet, men jeg kan kun se at der er MINDRE refractoring i dette her en i ASP.NET pga. en alting er string baseret i forhold til Managed Beans osv.


Det er så også en misforståelse.

Beans og brugen af dem i JSF understøtter skam andre typer end String.

Der er support for både alle standard typerne og får vilkårlige typer via custom convertere.

I PHP eller ASP.NET ville overstående kunne laves med halv så mange linjers kode


Formentligt kunne det gøres med færre linier kode i disse.

Men færre linier er ikke nødvendigvis bedre.

Nu har jeg arbejdet lidt med JSF her, og vil høre om der er nogen som rent faktisk kan give en god grund til at jeg overhovedet bør bruge 5min mere på dette her framework.


Så hvis der er nogen som har nogle guldkorn for hvorfor det er værd overhovedet at lære denne teknologi, så sig frem.


Jeg håber ikke at nogen har forsøgt at bilde dig ind at JSF er en teknologi som er nem at lære, fordi så har de bildt dig noget ind.

Det er en ret kompleks teknologi. Som bygger oven på en hel række andre teknologier.

Min JSF bog har 13 kapitler. Dit eksempel dækker kapitel 1 (Getting Started) og vel ca. halvdelen af kapitlerne 2, 3 og 4.

Det er ikke noget specielt godt grundlag for at evaluere JSF på.

Det er dog muligvis hvad det er realistisk at nå i en undervisnings sammenhæng.

Jeg ville ikke blive spor overrasket, hvis du fortalte mig, at du var den på holdet/klassen, som er nået længst ind i JSF's forunderlige verden.

Men til inspiration for dig og de øvrige læsere (sikkert ikke mange - de fleste stod nok af for en 50 indlæg siden) har jeg prøvet at arbejde lidt videre på dit eksempel.



Gravatar #137 - arne_v
4. jun. 2009 02:20
Første trin er at:
1) rydde op i backing beanen
* fjerne de overflødige settere
* ændre svaret til at være heltal fremfor streng
2) rydde lidt op i de mange conditionals i JSP side ved at ændre lidt i den og backing beanen
3) rydde lidt op i navigations flowet
4) være lidt mere konsekvent med localization

(udover disse ændringer har jeg også lavet et par andre småændringer bare fordi jeg skriver HTML anderledes læs mere primitivt end dig)

Efter disse ændringer ser det ud som:

Quiz.java


package website.quiz;

import java.util.List;
import java.util.ArrayList;

public class Quiz {
private final int MAX_TRIES = 3;
private List<QuizQuestion> questions;
private int questionIndex;
private boolean wrong;
private int numTries;
private Integer answer;
public Quiz() {
questions = new ArrayList<QuizQuestion>();
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));
questionIndex = 0;
numTries = 0;
}
public int getMaxTries() {
return MAX_TRIES;
}
public int getNumQuestions() {
return questions.size();
}
public QuizQuestion getQuestion() {
return questions.get(questionIndex);
}
public int getQuestionIndex() {
return questionIndex;
}
public boolean getWrong() {
return wrong;
}
public Integer getAnswer() {
return null;
}
public void setAnswer(Integer answer) {
this.answer = answer;
}
public String answerQuestion() {
if(questions.get(questionIndex).getAnswer() == answer.intValue()) {
questionIndex++;
if(questionIndex >= questions.size()) {
return "completed";
} else {
wrong = false;
return "continue";
}
} else {
numTries++;
if(numTries >= MAX_TRIES) {
return "failed";
} else {
wrong = true;
return "continue";
}
}
}
}


quiz.jsp


<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
<f:loadBundle var="locale" basename="website.resources.Localization"/>
<!doctype html public "-//w3c/dtd HTML 4.01 Transitional//en">
<html>
<head>
<title><h:outputText value="#{locale['quiz']}"/></title>
</head>
<body>
<h1><h:outputText value="#{locale['quiz']}"/></h1>
<h2><h:outputText value="#{locale['question']}"/>: <h:outputText value="#{quiz.questionIndex + 1}"/> / <h:outputText value="#{quiz.numQuestions}"/></h2>
<h:outputText rendered="#{quiz.wrong}" value="#{locale['wrongAnswer']}"/>
<h:form id="quiz">
<h:outputText value="#{quiz.question.question}"/> = <h:inputText id="answer" value="#{quiz.answer}"/>
<br>
<h:commandButton action="#{quiz.answerQuestion}" value="#{locale['answer']}"/>
</h:form>
</body>
</html>
</f:view>


faces-config.xml


<?xml version="1.0"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd http://java.sun.com/xml/ns/javaee/web-facesconfig_...
version="1.2">
<navigation-rule>
<from-view-id>/quiz.jsp</from-view-id>
<navigation-case>
<from-outcome>continue</from-outcome>
<to-view-id>/quiz.jsp</to-view-id>
<redirect/>
</navigation-case>
<navigation-case>
<from-outcome>completed</from-outcome>
<to-view-id>/completed.jsp</to-view-id>
<redirect/>
</navigation-case>
<navigation-case>
<from-outcome>failed</from-outcome>
<to-view-id>/failed.jsp</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
<managed-bean>
<managed-bean-name>quiz</managed-bean-name>
<managed-bean-class>website.quiz.Quiz</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>


Gravatar #138 - arne_v
4. jun. 2009 02:22
Næste trin er at:
- ændre spørgsmål fra hardcoded til konfigurerbart
- tilføje data validering på svaret
- splitte faces-config.xml op i flere filer

Efter disse ændringer ser det ud som:

Quiz.java


package website.quiz;

import java.util.List;
import java.util.ArrayList;

public class Quiz {
private int maxTries;
private List<QuizQuestion> questions;
private int questionIndex;
private boolean wrong;
private int numTries;
private Integer answer;
public Quiz() {
questionIndex = 0;
numTries = 0;
}
public int getMaxTries() {
return maxTries;
}
public void setMaxTries(int maxTries) {
this.maxTries = maxTries;
}
public void setQuestions(List<QuizQuestion> questions) {
this.questions = questions;
}
public int getNumQuestions() {
return questions.size();
}
public QuizQuestion getQuestion() {
return questions.get(questionIndex);
}
public int getQuestionIndex() {
return questionIndex;
}
public boolean getWrong() {
return wrong;
}
public Integer getAnswer() {
return null;
}
public void setAnswer(Integer answer) {
this.answer = answer;
}
public String answerQuestion() {
if(questions.get(questionIndex).getAnswer() == answer.intValue()) {
questionIndex++;
if(questionIndex >= questions.size()) {
return "completed";
} else {
wrong = false;
return "continue";
}
} else {
numTries++;
if(numTries >= maxTries) {
return "failed";
} else {
wrong = true;
return "continue";
}
}
}
}


quiz.jsp


<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
<!doctype html public "-//w3c/dtd HTML 4.01 Transitional//en">
<html>
<head>
<title><h:outputText value="#{locale['quiz']}"/></title>
</head>
<body>
<h1><h:outputText value="#{locale['quiz']}"/></h1>
<h2><h:outputText value="#{locale['question']}"/>: <h:outputText value="#{quiz.questionIndex + 1}"/> / <h:outputText value="#{quiz.numQuestions}"/></h2>
<h:outputText rendered="#{quiz.wrong}" value="#{locale['wrongAnswer']}"/>
<h:form id="quiz">
<h:outputText value="#{quiz.question.question}"/> = <h:inputText id="answer" value="#{quiz.answer}" required="yes" requiredMessage="#{locale['required']}" converterMessage="#{locale['notInteger']}" validatorMessage="#{locale['notPositive']}"><f:validateLongRange minimum="0"/></h:inputText> <h:message for="answer"/>
<br>
<h:commandButton action="#{quiz.answerQuestion}" value="#{locale['answer']}"/>
</h:form>
</body>
</html>
</f:view>


messages.xml


<?xml version="1.0"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd http://java.sun.com/xml/ns/javaee/web-facesconfig_...
version="1.2">
<application>
<resource-bundle>
<base-name>website.resources.Localization</base-name>
<var>locale</var>
</resource-bundle>
</application>
</faces-config>


navigation.xml


<?xml version="1.0"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd http://java.sun.com/xml/ns/javaee/web-facesconfig_...
version="1.2">
<navigation-rule>
<from-view-id>/quiz.jsp</from-view-id>
<navigation-case>
<from-outcome>continue</from-outcome>
<to-view-id>/quiz.jsp</to-view-id>
<redirect/>
</navigation-case>
<navigation-case>
<from-outcome>completed</from-outcome>
<to-view-id>/completed.jsp</to-view-id>
<redirect/>
</navigation-case>
<navigation-case>
<from-outcome>failed</from-outcome>
<to-view-id>/failed.jsp</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
</faces-config>


beans.xml


<?xml version="1.0"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd http://java.sun.com/xml/ns/javaee/web-facesconfig_...
version="1.2">
<managed-bean>
<managed-bean-name>quiz</managed-bean-name>
<managed-bean-class>website.quiz.Quiz</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>maxTries</property-name>
<value>3</value>
</managed-property>
<managed-property>
<property-name>questions</property-name>
<list-entries>
<value-class>website.quiz.QuizQuestion</value-class>
<value>#{q1}</value>
<value>#{q2}</value>
<value>#{q3}</value>
<value>#{q4}</value>
<value>#{q5}</value>
</list-entries>
</managed-property>
</managed-bean>
<managed-bean>
<managed-bean-name>q1</managed-bean-name>
<managed-bean-class>website.quiz.QuizQuestion</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>question</property-name>
<value>2+2</value>
</managed-property>
<managed-property>
<property-name>answer</property-name>
<value>4</value>
</managed-property>
</managed-bean>
<managed-bean>
<managed-bean-name>q2</managed-bean-name>
<managed-bean-class>website.quiz.QuizQuestion</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>question</property-name>
<value>2-2</value>
</managed-property>
<managed-property>
<property-name>answer</property-name>
<value>0</value>
</managed-property>
</managed-bean>
<managed-bean>
<managed-bean-name>q3</managed-bean-name>
<managed-bean-class>website.quiz.QuizQuestion</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>question</property-name>
<value>2*2</value>
</managed-property>
<managed-property>
<property-name>answer</property-name>
<value>4</value>
</managed-property>
</managed-bean>
<managed-bean>
<managed-bean-name>q4</managed-bean-name>
<managed-bean-class>website.quiz.QuizQuestion</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>question</property-name>
<value>2/2</value>
</managed-property>
<managed-property>
<property-name>answer</property-name>
<value>1</value>
</managed-property>
</managed-bean>
<managed-bean>
<managed-bean-name>q5</managed-bean-name>
<managed-bean-class>website.quiz.QuizQuestion</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>question</property-name>
<value>2^2</value>
</managed-property>
<managed-property>
<property-name>answer</property-name>
<value>4</value>
</managed-property>
</managed-bean>
</faces-config>


Gravatar #139 - arne_v
4. jun. 2009 02:28
Applikationen er ikke blevet mindre. Tværtimod.

Men hver fil har sin klart afgrænsede funktion:

web.xml - instruktioner til serveren
messages.xml - reference til localization filer
navigation.xml - flowet i applikationen
beans.xml - spørgsmålene til quizen
quiz.jsp - skærm med quiz
completed.jsp - skærm for bestået
failed.jsp - skærm for dumpet
Localization.properties - engelske tekster
Localization_da_DK.properties - danske tekster
Quiz.java - model for en hel quiz
QuizQuestion.java - model for et enkelt spørgsmål

Det kan man så mene er uendeligt overflødigt eller uendeligt smukt alt efter præferencer.

Det er så oppe på og bruge 4.5 kapitler ud af 13 i min JSF bog.

Der er stadig masser af yderligere finesser.


Gravatar #140 - arne_v
4. jun. 2009 02:30
Jeg synes at kode formateringen ser forfærdelig ud her. Hvis du eller andre gerne vil have den som en zip fil, så smid en email.
Gravatar #141 - Windcape
4. jun. 2009 09:24
Nu begynder det ihvertfald at se mere meningsfuldt ud :) Jeg kan bedre forholde mig til at splitte konfigurationen op i flere filer.

Og ja, newz.dk's kode blocks er horrible, så du må gerne maile det til min email:

[email protected]

Jeg har afsat en god del tid af læseferien til JSF, og jeg synes altid best-pratice gør kode nemmere at skrive.
Gravatar #142 - arne_v
4. jun. 2009 13:05
Jeg emailer det i aften (EST-DST).

Jeg vil iøvrigt ikke garantere at det er best practice. Det var kun hvad jeg kunne bixe sammen.

:-)

Gravatar #143 - arne_v
6. jun. 2009 13:49
1 - med cleanup
2 - med validering og mere konfiguration

sendt.

3a - med brug af Richfaces
3b - med brug af Facelets fremfor JSP

også sendt.
Gå til top

Opret dig som bruger i dag

Det er gratis, og du binder dig ikke til noget.

Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.

Opret Bruger Login