JavaとJavaEEプログラマのブログ

JavaEEを中心にしたをソフトウェア開発についてのブログ

JavaEE6入門〜Message Driven Bean〜

Message Driven Bean略してMDBはJMS(JavaMessaeService)を利用して非同期処理を実現する仕組み。

JMSの配信モデルは次の二種類。

  • Queueを使って送信側(プロデューサー)と受信側(コンシューマー)が一対一で送受信を行うP2P(Point to Point)モデル
  • Topicを使って一つの送信側(プロデューサー)と複数の受信側(コンシューマー)が一対多で送受信を行うpub-sub(パブリッシュ・サブスクライブ)モデル。

JMSが使用するQueueやTopicはGlassFishに組み込まれているメッセージング・プロバイダ(OpenMQ)が提供する。
MDBEJBの一種、状態を持たないStateless Beanとして管理される。そのためトランザクションアノテーションによる依存性注入もEJBと同じ。

MDBはWebプロファイルに含まれないため、warに含めてデプロイすることは出来ない。jarファイルかearアーカイブにパッケージ化してデプロイする。


受信側(コンシューマー)MDBの例

/**
 @MessageDrivenアノテーションとMessageListenerインターフェースを実装したクラスがMDB。
 このクラスをjarにしてGlassFishのメッセージングプロバイダにデプロイすると、メッセージを受信する度に、onMessage()が実行される。
 mappedName属性でJMS接続先を指定。
 activationConfig属性でJMSのプロパティを設定している。
 activationConfig属性で受信するメッセージを絞り込むことができる。
 activationConfig属性はメッセージング・プロバイダ依存。
*/
@MessageDriven(mappedName="jms/javaee6/ToipcM" 
        ,activationConfig={@ActivationConfigProperty(propertyName="acknowledgeMode",propertyValue="Auto-acknowledgeMode")
        ,@ActivationConfigProperty(propertyName="messageSelector",propertyValue="orderAmout > 1000")
        })
public class ConsumerMBean implements MessageListener{
    
    // EJBと同じようにリソースを注入できる。
    @PersistenceContext
    private EntityManager em;
    
    @EJB
    private BusinessEJB ejb;
    
    // コンテナが提供するランタイム・コンテキスト
    @Resource
    private MessageDrivenContext ctx; 
    
    @Override
    public void onMessage(Message message) {
        TextMessage msg = (TextMessage)message;
        try {
            System.out.println(msg.getText());
            // JMSを使って新たにメッセージを送信することも出来る。

        } catch (JMSException ex) {
            Logger.getLogger(ConsumerMBean.class.getName()).log(Level.SEVERE, null, ex);
            
            // メソッド終了後にロールバックを指定している。実行時例外を投げてもロールバックが実行される。
            ctx.setRollbackOnly();
        }
    }
}


送信側(プロデューサー)の例

/**
 普通のJavaクラス。ここではステートレスのEJBにしている。
*/
@Stateless
public class ProducerEJB {
    // JMSのリソースを注入。
    @Resource(lookup = "jms/javaee6/ConnectionFactory")
    private static ConnectionFactory connectionFactory;
    
    @Resource(lookup = "jms/javaee6/Queue")
    private static Queue queue;

    public void sendMessage(Message msg) {
        try {

            /*
                OrderDTOはメッセージ送信用のオブジェクト。
                OrderDTOはSerializableを実装している。
            */
            Float totalAmount = Float.valueOf(129000);
            OrderDTO order = new OrderDTO(1234l, new Date(), "Serge Gainsbourg", totalAmount);

            // Creates the needed artifacts to connect to the queue
            Connection connection = connectionFactory.createConnection();
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageProducer producer = session.createProducer(queue);

            // Sends an object message to the queue
            ObjectMessage message = session.createObjectMessage();
            message.setObject(order);
            message.setFloatProperty("orderAmount", totalAmount);
            producer.send(message);
            System.out.println("\nMessage sent : " + order.toString());

            connection.close();
        } catch (JMSException ex) {
            Logger.getLogger(ProducerEJB.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
}

JPAが発行するSQLが予約語とぶつかったときのエラー

Orderエンティテイーを作り、テストケースでデータをinsert仕様とすると以下のエラーが出た。

原因はDerby予約語に"ORDER"が存在するため。
Orderクラスの@Entity を @Entity(name="ORDER_Product")に修正して解決。

Derbyの予約語一覧

Testcase: testInsert(biz.solidc.study.jpa.jpastudy.oneToOne.OneToOneTest):	Caused an ERROR
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: Syntax error: Encountered "ORDER" at line 1, column 13.
Error Code: 20000
Call: INSERT INTO ORDER (ID, NAME, PRODUCT_ID) VALUES (?, ?, ?)
	bind => [2,製品A-001, 1]
Query: InsertObjectQuery(biz.solidc.study.jpa.jpastudy.oneToOne.Order[ id=2 ])
javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: Syntax error: Encountered "ORDER" at line 1, column 13.
Error Code: 20000
Call: INSERT INTO ORDER (ID, NAME, PRODUCT_ID) VALUES (?, ?, ?)
	bind => [2, 製品A-001, 1]
Query: InsertObjectQuery(biz.solidc.study.jpa.jpastudy.oneToOne.Order[ id=2 ])
	at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102)
	at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63)
	at biz.solidc.study.jpa.jpastudy.oneToOne.OneToOneTest.testInsert(OneToOneTest.java:44)
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: Syntax error: Encountered "ORDER" at line 1, column 13.
Error Code: 20000
Call: INSERT INTO ORDER (ID, NAME, PRODUCT_ID) VALUES (?, ?, ?)
	bind => [2, 製品A-001, 1]
Query: InsertObjectQuery(biz.solidc.study.jpa.jpastudy.oneToOne.Order[ id=2 ])
	at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:644)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:535)
	at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1717)
	at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:253)
	at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:207)
	at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:193)
	at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:342)
	at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:162)
	at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:177)
	at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:472)
	at org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:80)
	at org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:90)
	at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:287)
	at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
	at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:844)
	at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:743)
	at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
	at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2871)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1516)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1498)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1449)
	at org.eclipse.persistence.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:224)
	at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsForClassWithChangeSet(CommitManager.java:191)
	at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:136)
	at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:3799)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1415)
	at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:636)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1505)
	at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:267)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1143)
	at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:84)
Caused by: java.sql.SQLSyntaxErrorException: Syntax error: Encountered "ORDER" at line 1, column 13.
	at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source)
	at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
	at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(Unknown Source)
	at org.apache.derby.impl.jdbc.TransactionResourceImpl.handleException(Unknown Source)
	at org.apache.derby.impl.jdbc.EmbedConnection.handleException(Unknown Source)
	at org.apache.derby.impl.jdbc.ConnectionChild.handleException(Unknown Source)
	at org.apache.derby.impl.jdbc.EmbedPreparedStatement.<init>(Unknown Source)
	at org.apache.derby.impl.jdbc.EmbedPreparedStatement20.<init>(Unknown Source)
	at org.apache.derby.impl.jdbc.EmbedPreparedStatement30.<init>(Unknown Source)
	at org.apache.derby.impl.jdbc.EmbedPreparedStatement40.<init>(Unknown Source)
	at org.apache.derby.jdbc.Driver40.newEmbedPreparedStatement(Unknown Source)
	at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown Source)
	at org.apache.derby.impl.jdbc.EmbedConnection.prepareStatement(Unknown Source)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.prepareStatement(DatabaseAccessor.java:1474)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.prepareStatement(DatabaseAccessor.java:1423)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseCall.prepareStatement(DatabaseCall.java:697)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:585)
Caused by: java.sql.SQLException: Syntax error: Encountered "ORDER" at line 1, column 13.
	at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
	at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(Unknown Source)
Caused by: ERROR 42X01: Syntax error: Encountered "ORDER" at line 1, column 13.
	at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
	at org.apache.derby.impl.sql.compile.ParserImpl.parseStatement(Unknown Source)
	at org.apache.derby.impl.sql.GenericStatement.prepMinion(Unknown Source)
	at org.apache.derby.impl.sql.GenericStatement.prepare(Unknown Source)
	at org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext.prepareInternalStatement(Unknown Source)

の設定が無い場合のエラー

テストケースの実行が不定期に失敗する時に発生しているエラー。
JPAがEntityクラスの読み込みに失敗しているらしい。
persistence.xmlタグで使用するEntityクラスを指定してやると解決。
タグの追加はEntityクラスの新規作成ウィザードを使えばNetBeansが自動で挿入してくれるし、手入力でもEntityクラスだけに絞り込んで補完してくれるので大して手間はかからない。

java.lang.IllegalArgumentException: Object: biz.solidc.study.jpa.jpastudy.oneToMany.Customer@3f5b422e[orders=[biz.solidc.study.jpa.jpastudy.oneToOne.Order@4ad23a8f[product=biz.solidc.study.jpa.jpastudy.oneToOne.Product@423d8285[id=1,name=製品-A],id=3,name=注文1], biz.solidc.study.jpa.jpastudy.oneToOne.Order@3002a8a9[product=biz.solidc.study.jpa.jpastudy.oneToOne.Product@e48c264[id=2,name=製品-B],id=4,name=注文2]],id=<null>,name=顧客太郎,tel=777-090-9888] is not a known entity type.
testInsert(biz.solidc.study.jpa.jpastudy.oneWay.oneToOne.OneToOneTest)  Time elapsed: 0.017 sec  <<< ERROR!
javax.persistence.RollbackException: java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: biz.solidc.study.jpa.jpastudy.oneWay.oneToOne.Product@49bcb0d6[id=<null>,name=製品-A].
	at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102)
	at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63)
	at biz.solidc.study.jpa.jpastudy.oneWay.oneToOne.OneToOneTest.testInsert(OneToOneTest.java:42)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:601)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
	at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
	

persistence.xmlのが実行環境とテスト環境で異なっている場合のエラー。

エンティティクラスがis not a known entity type.と指摘されている。
エンティティクラスをタグで設定しても良いが、persistence.xmlを実行環境とテスト環境で同じにするのが根本的な解決。

実行環境とテスト環境の切り替えはを変えて行わずに、mavenなどに任せるべき。

-------------------------------------------------------------------------------
Test set: biz.solidc.study.jpa.jpastudy.oneToMany.OneToManyTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.149 sec <<< FAILURE!
testInsert(biz.solidc.study.jpa.jpastudy.oneToMany.OneToManyTest)  Time elapsed: 0.01 sec  <<< ERROR!
java.lang.IllegalArgumentException: Object: biz.solidc.study.jpa.jpastudy.oneToMany.Customer@3f5b422e[orders=[biz.solidc.study.jpa.jpastudy.oneToOne.Order@4ad23a8f[product=biz.solidc.study.jpa.jpastudy.oneToOne.Product@423d8285[id=1,name=製品-A],id=3,name=注文1], biz.solidc.study.jpa.jpastudy.oneToOne.Order@3002a8a9[product=biz.solidc.study.jpa.jpastudy.oneToOne.Product@e48c264[id=2,name=製品-B],id=4,name=注文2]],id=<null>,name=顧客太郎,tel=777-090-9888] is not a known entity type.
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist(UnitOfWorkImpl.java:4169)
	at org.eclipse.persistence.internal.jpa.EntityManagerImpl.persist(EntityManagerImpl.java:440)
	at biz.solidc.study.jpa.jpastudy.oneToMany.OneToManyTest.testInsert(OneToManyTest.java:58)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:601)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
	at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
	at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:53)
	at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:123)
	at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:104)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:601)
	at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:164)
	at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:110)
	at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:175)
	at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcessWhenForked(SurefireStarter.java:107)
	at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:68)

JavaEE6入門〜JSF2.0 Ajax〜

詳細はこちら。
JSF 2.0 の Ajax 対応はとてもかんたん

タグを使って、Ajaxの対象となるイベントやレンダリング対象を指定するだけ。

jQueryと連携したい場合はこちらを参照。JSF2.0に付属しているjsf.jsを使って連携を行う。
jQuery UI ダイアログとJSF2.0の連携

JavaEE6入門〜JSF2.0 カスタムコンバータとバリデータ〜

画面の入力値をStringから他の型へ変換するのがコンバータ。

    <h:inputText value="#{myBookController06.book.price}" >
        <!-- 文字列を数値に変換する。myBookController06.book.priceに応じてNetBeasnsが補完してくれる。 -->
        <f:convertNumber  /> 

        <!-- 文字数を検証するバリデータ -->
        <f:validateLength minimum="2" maximum="20" />
    </h:inputText>

    <td>
        <h:inputText value="#{myBookController06.book.title}"/>
        <!-- カスタムコンバータの例
        @FacesConverter(value="customTitleConvertor") が付加され、Converterインターフェースを実装したクラスに関連づけられる。
        
        -->        
        <f:convertNumber  converterId="customTitleConvertor" /> 

        <!-- カスタムバリデータの例
        @FacesValidator(value="customValidator") が付加され、Validatorインターフェースを実装したクラスに関連づけられる。
        
        -->        
        <f:validator  converterId="customValidator" /> 
        
    </td>

    <!-- コンバータとバリデータは以下のように属性で指定することも可能。 -->
    <h:inputText 
        value="#{myBookController06.book.title}" 
        converter="customTitleConvertor" 
        validator="customValidator"
    />

    
@FaceConverter(value="customTitleConvertor")
public class CustomTitleConvertor implements Converter{

    /**
     画面を構成しているUIコンポーネントに入力された文字列を、別のオブジェクトに変換する。
     変換が失敗した場合にはConverterExceptionを投げる。
    */
    @Override
    public Object getAsObject(){}

    /**
     getAsObjectとは逆にオブジェクトをUIコンポーネントに表示する文字列に変換する。
     変換が失敗した場合にはConverterExceptionを投げる。
    */
    @Override
    public String getAsString(){}

}

@FacesValidator(value="customValidator")
public class CustomValidator implements Validator{

    /**
     バリデートで検証エラーが発生した場合にはValidatorExceptionを投げる。
    */
    @Override
    public Object validate(){}

}

<||


*1350898525*[javaEE6][JSF2]JavaEE6入門〜JSF2.0 マネージドBean〜

最新の解説はこちらを参照。
[http://yoshio3.com/2012/08/24/detail-of-jsf20/:title=JSF 2.0 の詳細について]

JSF2.0は大きく分けると、クライアントに対する画面を作るコンポーネントとコンポーネントに必要なデータを渡したり、コンポーネント間のページ遷移を制御するマネージドBeanからなる。
マネージドBeanの作り方はPOJOに@ManaedBeanを付けるだけ。NetBeansでは右クリック→新規→JSF管理対象 Bean で作成できる。
マネージドBean内のpublicメソッドはコンポーネント内からEL式で使用することができる。

マネージドBeanの例↓
>|java|
// マネージドBeanであることを示すアノテーション
// eager=true はアプリケーション起動時にインスタンスを即時生成する設定。
@ManagedBean(eager=true)
/*
スコープ指定用のアノテーション。範囲が広い順にapplication、session、view、request、flash、noneがある。アノテーションが無い場合のデフォルトはrequest。
このうち、flushはアノテーションではなくJSFの暗黙オブジェクト:flushを使用して実現するスコープ。
noneはJSFページからアクセス不可で、他のマネージドBeanからアクセスできるスコープ。
*/
@ViewScoped
public class StartPageController{

	@EJB
	private BussinesssLogicEJB logicEJB;

	private Result result = new Result();

	// 任意の値を注入するアノテーション。ビューがレンダリングされる時に設定される。
	// ↓ではOtherクラスのotherDishを設定している。
	@ManagedProperty(value = "#{other.otherDish}")
	private Dish dish;

	// こういった文字列や数値の注入はfaces-config.xmlで設定できる。
	@ManagedProperty(value = "タイトル")
	private String title;
	

	// インスタンス生成時に実行したいメソッドに付けるアノテーション
	@PostContruct
	publi init(){
	}

	// インスタンス消滅時に実行したいメソッドに付けるアノテーション
	@PreDestroy
	public flush(){
	}

	public String doRegistBusiness(){
		result = logicEJB.doBusiness();

		/*
		  遷移先の画面を返している。拡張子は省略可。
		  nullを返すと現在のページをリロードする。
		  遷移先の設定はfaces-config.xmlでも可能。グローバルな遷移はfaces-config.xmlに設定するべき。faces-config.xmlではEL式を使った条件分岐も可能。
		*/
		return "endBusiness.xhtml";
	}

	public String (){

		/*
		 画面上で暗黙オブジェクトflashを使い、EL式 #{flash.flashKey} で"フラッシュ!"を取り出せる。
		*/
        Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
        flash.put("flashKey", "フラッシュ!");

        return "endBusiness";
    }


	public Result getResult(){

		// 画面にメッセージを表示するときはFacesContext.addmessage()を使う。
		// ctx.addMessage にDOM式を指定すると<h:form id="mainForm"><h:message for="title"/></h:form>タグで指定した場所にメッセージが表示される。
		// nullを指定するとグローバルメッセージとして<h:messages/>タグの場所に表示される。
		FacesContext ctx = FacesContext.getCurrentInstance();
		
		ctx.addMessage(
			"mainForm.title", // formのid:テキストフィールドのidのDOM式
			new FacesMessage(
				FacesMessage.SERVRTITY_INFO,
				"isbn number",
				"ISBNが表示されます。"
			
			)
		);
		return result;
	}
}