...少なくとも、 "エレガントな回避策"のコンセプトが実際にメリットがあるならば!ここでWeld(CDI)とDatanucleus(JPA)はうまくいきませんが、エレガントな回避策はありますか?
は、いくつかの詳細は以下のとおりです。
CDIとJPAを使用している場合、あなたは多くの場合、そのように、あなたのJSFページのいずれかにEL式であなたのJPA-管理対象Beanのいずれかにアクセスしたいと思う:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>An Everyday Facelet</title>
</h:head>
<h:body>
<h1>Behold, a jpa-managed bean property!</h1>
<h:outputText value="#{exampleEntity.name}" />
</h:body>
</html>
わかりやすくするために、このページはHTTP Postの結果であり、クライアントは前のページのnameプロパティの値を入力したと仮定します。豆自体はそうのような、プロデューサメソッドから取得したシンプルなJPAエンティティとすることができます。
@Entity
public class ExampleEntity implements Serializable {
@Id
@Column
private Long entityId;
@Column
private String name;
public ExampleEntity() {
}
public void setEntityId(Long entityId) {
this.entityId = entityId;
}
public Long getEntityId() {
return entityId;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// Some method in another class
public class AnotherClass {
@Produces
@RequestScoped
@Named("exampleEntity")
public ExampleEntity getExampleEntity() {
return new ExampleEntity();
}
}
すべての権利、のコンパイルしましょう。データ核JPA実装の1つの重要な側面は、コンパイル後のステップがあることです。コンパイルされたjpaクラスでバイトコードエンハンサーを実行する必要があるので、それを仮定しましょう。サーブレットコンテナ(Tomcat、Jetty)を起動しようとすると、Weldを起動するときに例外が発生します(実際にこのBeanをどこかに注入しようとすると、複数の例外が発生します)。
org.jboss.weld.exceptions.UnproxyableResolutionException: WELD-001437 Normal scoped bean class testapp.ExampleEntity is not proxyable because the type is final or it contains a final method public final java.lang.Object testapp.ExampleEntity.jdoGetObjectId() - Managed Bean [class testapp.ExampleEntity] with qualifiers [@Any @Default @Named].
公共最終java.lang.ObjectのjdoGetObjectId():私のクラスは 'testappと' パッケージであると仮定すると、例外のようなものでしょうか?私はそれらの1つ、良いWebサーバーを定義も宣言もしていません。あなたは間違っている必要があります!
データ核エンハンサーは、この最終メソッドをコンパイル済みクラスに追加する必要があります。私のデータが実際には残っていないとは思いますが、Webサーバは実行しなければ正常に起動します。少しの研究で、Weldのドキュメントで問題の説明を見つけることができました:http://docs.jboss.org/weld/reference/1.1.5.Final/en-US/html/injection.html#d0e1429
要するに、名前の付いた豆が最終的な方法を持つことはできません。そこのアドバイスの一部に続いて、私は実用的な解決策を見つけました。私はjpa beanのインターフェースを宣言し、具象クラス(実際にはデータ核強化クラスですが、Weldは知らない)を得るためのプロデューサメソッドを作成します。ここでは、追加のコードは次のとおりです。
public interface ExampleEntity {
public Long getEntityId();
public void setEntityId(Long entityId);
public String getName();
public void setName(String name);
}
今ExampleEntityは純粋インターフェイスであることを、私はCDI注釈なし
@Entity
public class ExampleEntityImpl implements ExampleEntity, Serializable {
// Same as the ExampleEntity class above
}
をJPA管理の実装を作成し、最終的には、おそらくコントローラのどこかに、私はプロデューサーを定義しますExampleEntitiesを取得する方法
@Named("exampleEntityController")
@RequestScoped
public class ExampleEntityController {
private ExampleEntity newExampleEntity;
public ExampleEntityController() {
newExampleEntity = new ExampleEntityImpl();
}
// The producer method
@Produces
@RequestScoped
@Named("exampleEntity")
public ExampleEntity getExampleEntity() {
return newExampleEntity;
}
// Other stuff, because surely a controller does more than just this, right?
}
...これが動作します。 Webサーバーが起動しますが、例外はありません。 name属性は、そのサンプルのfaceletで適切に取得されます(データが前のページにすでに入力されていると仮定します)。しかし、すべてのJSP管理されたBeanのための一回限りのインターフェースとプロデューサメソッドを作ることはかなり冗長で醜いです。より良い解決策はありますか? Datanucleusはこのプロジェクトの要件ですので、私は単純に他のものを使うことはできません。より洗練された回避策がある場合、Weldに私の名前の豆の中で決して使うことのない最終的な方法を持たせるためのより良い方法があると思います。
編集:応答/訂正ありがとうございますが、各jpa beanのインタフェースを作成する必要がない方法を探しています。私は例からJPA/CDIの注釈を混ぜて削除しましたが、Webサーバーは関係なく同じ例外をスローします。私はどちらの方法でもプロデューサーメソッドが必要であることがわかります。
を処理することができるようにCDIのBeanは、コンテナによって作成され
new
演算子を使用して、どのように@Named 'に来ました'' @ RequestScoped' '@ Entity'? – Oswこの例ではスコープは任意ですが、JPA APIを使用して永続化することもできる名前付きBeanです。それはとにかく目標です。これは、完全なアプリケーションサーバーで私のために働く。 – Shaun
DataNucleusのバイトコード拡張機能は、http://db.apache.org/jdo/enhancement.htmlの標準化されたAPIに多くのメソッドを追加します。 – DataNucleus