1.4.3.2. numberguess クイックスタート
概要
このクイックスタートでは、簡単なアプリケーションを作成して JBoss EAP 6 にデプロイする方法を示します。このアプリケーションは情報を保持しません。情報は JSF ビューを使用して表示され、ビジネスロジックは 2 つの CDI (コンテキストと依存性注入) Bean にカプセル化されます。numberguess クイックスタートでは、1 から 100 までの数字を推測する試みが 10 回行われます。数字を選択した後、その数字が正解の数字よりも大きいかまたは小さいかが表示されます。
numberguess のクイックスタートのコードは、
QUICKSTART_HOME/numberguess
ディレクトリーにあります。numberguess クイックスタートは複数の Bean、設定ファイル、および Facelets (JSF) ビューによって構成され、WAR モジュールとしてパッケージ化されています。
コマンドラインを使用してこのクイックスタートをビルドしデプロイする手順の詳細については、numberguess クイックスタートディレクトリーのルートにある README.html ファイルを参照してください。ここでは、Red Hat JBoss Developer Studio を使用してクイックスタートを実行する方法を示します。このトピックは、Red Hat JBoss Developer Studio をインストールし、Maven を設定し、
numberguess
クイックスタートをインポートして正常に実行したことを前提としています。
前提条件
- 以下の手順に従って、Red Hat JBossDeveloperStudio をインストールします。「Install Red Hat JBoss Developer Studio」。
- 以下の手順に従って、Red Hat JBoss Developer Studio で使用するように Maven を設定します。「Red Hat JBoss Developer Studio で使用するための Maven の設定」。
- こちらの手順に従って、Red Hat JBoss Developer Studio で
numberguess
クイックスタートをインポート、ビルド、およびデプロイします。 「Red Hat JBoss Developer Studio でクイックスタートを実行します」 - Web ブラウザーを開き、次の URL でアプリケーションにアクセスして、
numberguess
クイックスタートが JBoss EAP に正常にデプロイされたことを確認します。 http://localhost:8080/jboss-numberguess
手順1.11 設定ファイルの確認
この例のすべての設定ファイルは、クイックスタートの
src/main/webapp/
ディレクトリーにある WEB-INF/
ディレクトリーに配置されています。
faces-config.xml
ファイルを確認します。本クイックスタートはfaces-config.xml
ファイル名の JSF 2.0 バージョンを使用します。Facelets の標準化されたバージョンは JSF 2.0 のデフォルトのビューハンドラーであるため、実際に設定する必要はありません。JBoss EAP 6 は、ここで JavaEE を超えています。この設定ファイルを含めると、JSF が自動的に設定されます。その結果、設定はルート要素のみで設定されます。19. <faces-config version="2.0" 20. xmlns="http://java.sun.com/xml/ns/javaee" 21. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 22. xsi:schemaLocation=" 23. http://java.sun.com/xml/ns/javaee> 24. http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"> 25. 26. </faces-config>
beans.xml
ファイルを確認します。空のbeans.xml
ファイルもあります。これは、JBoss EAP 6 にこのアプリケーションで Bean を検索し、CDI をアクティブ化するように指示します。web.xml
ファイルはありませんクイックスタートにはweb.xml
ファイルも必要ないことに注意してください。
手順1.12 JSF コードの確認
JSF はソースファイルに
.xhtml
ファイル拡張子を使用しますが、レンダリングされたビューは .jsf
拡張子で提供されます。
home.xhtml
コードを調べます。home.xhtml
ファイルはsrc/main/webapp/
ディレクトリーにあります。19. <html xmlns="http://www.w3.org/1999/xhtml" 20. xmlns:ui="http://java.sun.com/jsf/facelets" 21. xmlns:h="http://java.sun.com/jsf/html" 22. xmlns:f="http://java.sun.com/jsf/core"> 23. 24. <head> 25. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> 26. <title>Numberguess</title> 27. </head> 28. 29. <body> 30. <div id="content"> 31. <h1>Guess a number...</h1> 32. <h:form id="numberGuess"> 33. 34. <!-- Feedback for the user on their guess --> 35. <div style="color: red"> 36. <h:messages id="messages" globalOnly="false" /> 37. <h:outputText id="Higher" value="Higher!" 38. rendered="#{game.number gt game.guess and game.guess ne 0}" /> 39. <h:outputText id="Lower" value="Lower!" 40. rendered="#{game.number lt game.guess and game.guess ne 0}" /> 41. </div> 42. 43. <!-- Instructions for the user --> 44. <div> 45. I'm thinking of a number between <span 46. id="numberGuess:smallest">#{game.smallest}</span> and <span 47. id="numberGuess:biggest">#{game.biggest}</span>. You have 48. #{game.remainingGuesses} guesses remaining. 49. </div> 50. 51. <!-- Input box for the users guess, plus a button to submit, and reset --> 52. <!-- These are bound using EL to our CDI beans --> 53. <div> 54. Your guess: 55. <h:inputText id="inputGuess" value="#{game.guess}" 56. required="true" size="3" 57. disabled="#{game.number eq game.guess}" 58. validator="#{game.validateNumberRange}" /> 59. <h:commandButton id="guessButton" value="Guess" 60. action="#{game.check}" 61. disabled="#{game.number eq game.guess}" /> 62. </div> 63. <div> 64. <h:commandButton id="restartButton" value="Reset" 65. action="#{game.reset}" immediate="true" /> 66. </div> 67. </h:form> 68. 69. </div> 70. 71. <br style="clear: both" /> 72. 73. </body> 74. </html>
表1.2 JSF の詳細 行 注記 36〜40 これらはユーザーに送信できるメッセージ、「Higher」(より大きい) と「Lower」(より小さい) です。 45〜48 ユーザーが数を選択するごとに数字の範囲が狭まります。有効な数の範囲が分かるようにこの文章は変更されます。 55〜58 この入力フィールドは値式を使用して Bean プロパティーにバインドされます。 58 ユーザーが誤って範囲外の数字を入力しないようにバリデーターのバインディングが使用されます。バリデーターがないと、ユーザーが範囲外の数字を使用する可能性があります。 59〜61 ユーザーの選択した数字をサーバーに送る方法がなければなりません。ここでは、Bean 上のアクションメソッドをバインドします。
手順1.13 クラスファイルの確認
すべての numberguess クイックスタートソースファイルは、
src/main/java/org/jboss/as/quickstarts/numberguess/
ディレクトリーにあります。パッケージの宣言とインポートはこれらのリストからは除外されています。完全リストはクイックスタートのソースコードで確認できます。
Random.java
修飾子コードの検証修飾子は、型を基にしたインジェクションの対象となる 2 つの bean 間のあいまいさを取り除くために使用されます。修飾語の詳細については、以下を参照してください。 「修飾子を使用したあいまいなインジェクションの解決」@Random
修飾子は乱数のインジェクトに使用されます。@Target({ TYPE, METHOD, PARAMETER, FIELD }) @Retention(RUNTIME) @Documented @Qualifier public @interface Random { }
MaxNumber.java
修飾子コードの検証@MaxNumber
qualifier
は最大許可数の挿入に使用されます。@Target({ TYPE, METHOD, PARAMETER, FIELD }) @Retention(RUNTIME) @Documented @Qualifier public @interface MaxNumber { }
Generator.java
コードの検証Generator
クラスは、プロデューサーメソッドを介して乱数を作成するロールを果たします。また、プロデューサーメソッドを介して可能な最大数を公開します。このクラスはアプリケーションスコープであるため、毎回異なる乱数になることはありません。@SuppressWarnings("serial") @ApplicationScoped public class Generator implements Serializable { private java.util.Random random = new java.util.Random(System.currentTimeMillis()); private int maxNumber = 100; java.util.Random getRandom() { return random; } @Produces @Random int next() { // a number between 1 and 100 return getRandom().nextInt(maxNumber - 1) + 1; } @Produces @MaxNumber int getMaxNumber() { return maxNumber; } }
Game.java
コードの検証セッションスコープのクラスGame
は、アプリケーションの主要なエントリーポイントです。ゲームの設定や再設定、ユーザーが選択する数字のキャプチャーや検証、FacesMessage
によるユーザーへのフィードバック提供を行います。コンストラクト後の lifecycle メソッドを使用し、@Random Instance
<Integer>
bean から乱数を取得することによりゲームを初期化します。このクラスの @Named アノテーションを見てください。このアノテーションは式言語 (EL) を使用して Bean が JSF ビューにアクセスできるようにしたい場合のみ必要です。この場合#{game}
が EL になります。@SuppressWarnings("serial") @Named @SessionScoped public class Game implements Serializable { /** * The number that the user needs to guess */ private int number; /** * The users latest guess */ private int guess; /** * The smallest number guessed so far (so we can track the valid guess range). */ private int smallest; /** * The largest number guessed so far */ private int biggest; /** * The number of guesses remaining */ private int remainingGuesses; /** * The maximum number we should ask them to guess */ @Inject @MaxNumber private int maxNumber; /** * The random number to guess */ @Inject @Random Instance<Integer> randomNumber; public Game() { } public int getNumber() { return number; } public int getGuess() { return guess; } public void setGuess(int guess) { this.guess = guess; } public int getSmallest() { return smallest; } public int getBiggest() { return biggest; } public int getRemainingGuesses() { return remainingGuesses; } /** * Check whether the current guess is correct, and update the biggest/smallest guesses as needed. Give feedback to the user * if they are correct. */ 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--; } /** * Reset the game, by putting all values back to their defaults, and getting a new random number. We also call this method * when the user starts playing for the first time using {@linkplain PostConstruct @PostConstruct} to set the initial * values. */ @PostConstruct public void reset() { this.smallest = 0; this.guess = 0; this.remainingGuesses = 10; this.biggest = maxNumber; this.number = randomNumber.get(); } /** * A JSF validation method which checks whether the guess is valid. It might not be valid because there are no guesses left, * or because the guess is not in range. * */ 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); } } }