こっちの記事に書いたけど、CDIが出来ちゃえば、後はもう簡単だよね。
CDI使ってるってことは、リソース系は、全部@Produces作ってるはずだから、
それを上書きしちゃえばok!
JPAは普通……かどうか分からないけど、CDI使っているなら、
persistence.xmlに定義しているUnitごとに、Producer作るよね。
たとえば、persistence.xmlにSamplePUが定義されてるとするとこんな感じ。
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE})
public @interface Sample {
}
@RequestScoped
public class SampleProducer {
@PersistenceContext(unitName="SamplePU")
private EntityManager em;
@Produces @Sample
public EntityManager getEntityManager() {
return this.em;
}
}
そしたら、テスト側はこんな感じのを用意すれば完成!テスト用のbeans.xmlに追加するの忘れないでね。
package jp.empressia.test;
// (略)
@Stereotype
@Alternative
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Documented
public @interface UnitTest {
}
@RequestScoped
public class LocalSampleProducer {
private static final EntityManagerFactory emf;
static {
emf = Persistence.createEntityManagerFactory("SamplePU");
}
private EntityManager em;
public LocalSampleProducer() {
this.em = emf.createEntityManager();
}
@Produces @Sample @UnitTest
public EntityManager getEntityManager() {
return this.em;
}
}
<beans>
<alternatives>
<stereotype>jp.empressia.test.UnitTest</stereotype>
</alternatives>
</beans>
EntityManagerFactoryとEntityManagerの扱い方はこれでいいよね、たぶん。
それから、JTAかな。
CDIとJTAなら、javax.transaction.Transactional使っているという前提で、Interceptorを作っちゃう方向でいいよね。
あと、ユニットテストだし、接続先は共通で1個だけってことにするよ。
まず、ProducerにTransactionを提供する部分を追加するのだ。
@RequestScoped
public class LocalSampleProducer {
// (略)
@Produces
public EntityTransaction getTransaction() {
return this.em.getTransaction();
}
}
そうしたら、こんな感じのInterceptorでも十分かなっと。
別にもっと作り込んでも良いんだけど、わたしはそんな高度な使い方しないしね。
package jp.empressia.test;
// (略)
@Transactional
@Interceptor
public class TransactionInterceptor {
@Inject
private EntityTransaction trans;
@AroundInvoke
public Object doTransaction(InvocationContext ic) throws Exception {
Object result = null;
try {
this.trans.begin();
result = ic.proceed();
if(this.trans.isActive()) {
if(this.trans.getRollbackOnly() == false) {
this.trans.commit();
} else {
this.trans.rollback();
}
} else {
String message = "なにかメッセージ";
logger(this).warning(message);
}
} catch(Exception proceededEx) {
try {
if(trans.isActive()) {
trans.rollback();
}
} catch(Exception rollbackEx) {
String message = "なにかメッセージ";
logger(this).severe(message);
}
throw proceededEx;
}
return result;
}
}
で、これを、やっぱりbeans.xmlにっと。
<beans>
<intercepters>
<class>jp.empressia.test.TransactionInterceptor</class>
</intercepters>
</beans>
これで、@TransactionalもEntityManagerのInjectも動くね。
ちなみに、前の記事のパッケージには、接続先のUnitが1個前提の実装が入ってるよ。
beans.xmlをこんな感じにすれば有効になるようになってる。
<beans>
<alternatives>
<stereotype>jp.empressia.test.UnitTest</stereotype>
</alternatives>
<intercepters>
<class>jp.empressia.test.TransactionInterceptor</class>
</intercepters>
</beans>
あとはLocalなEntityManagerなProducerをこんな感じに書けばok。
『@Sample』みたいな指定が元々なければ、子のクラスは用意する必要も無い……はず、たぶん。
@Inject EntityManagerが動作してるからね。
@RequestScoped
public class LocalSampleProducer {
@Inject
private EntityManager em;
@Produces @Sample @UnitTest
public EntityManager getEntityManager() {
return this.em;
}
}
あ、もしかしたら、EclipseLinkをjavaagentに指定して起動すれば、もっと簡単かもしれないけど、その辺は試してないよ。
<a href="http://www.gz27n37dn857oxbizr74uq8x411500qxs.org/">aytlvolxtbz</a>
ytlvolxtbz http://www.gz27n37dn857oxbizr74uq8x411500qxs.org/
[url=http://www.gz27n37dn857oxbizr74uq8x411500qxs.org/]uytlvolxtbz[/url]
ラルフローレン 福袋 中身 メンズ http://timesuptees.com/imaging/constructing-2751.html
アシックス ハンドボールシューズ http://www.colbycc.edu/thematically/mailer-kg2191a-607.html
ケイトスペード ギフトボックス http://www.ibis.slupsk.pl/simulation/spectroscope-1779.html
adidas ジーンズ 店舗 http://nutrimedtn.com/satin/200.html
オロビアンコ 神戸大丸 http://www.womenforworldhealth.org/prosperity/q-Yc1918.html
ティンバーランド 赤白紐の結び方 http://office.psru.ac.th/lying/give-2409.html
ジバンシー チーク 9 http://www.zs-pisecna.cz/reactivate/A-i345.html