一直在看DDD,自己感觉也可以搭建一个基本的开发环境了。但还是想综合看一下别人的成果。axonframwork看了几天了,感觉比isis更好上手,更加专注于领域模型,其他的事不管,挺好,而isis还有它自己定义的界面方案,不知道怎么摘出来,可能是我不够熟悉isis吧,感觉用的不舒服。之前读了axon的quickstart和那个 addressbook例子。addressbook使用的是spring。可是我一直不用spring了(因为那个恶心的数据源死锁问题),而是使用CDI来做注入之类的事情。我想把addressbook移植到CDI上,废了不少周折才基本可用,下面就是我主要的改动,自己做个记录。
主要问题:@CommandHandler,@EventHandler这种注解,可以直接放到一个pojo类的某个方法上,这样就没法通过普通的@Produces进行初始化,基本的java方式只能是用实现CommandHandler接口来做,但这样需要创建的handler类太多了。
另外,spring管理事务的功能肯定不能在cdi中使用了。
自己瞎鼓捣一阵子,基本注入都可以了,但是@CommandHandler和@EventHandler这种注解没搞定,忽然从他的mailing list中看到有人写了个axon-cdi的实现,在github上,能够帮我解决不少问题,自己写的话,CDI又要深入研究几天了。多谢作者!如果你要找这个实现,直接去github上搜就行了。
下面说说我关键几个地方的配置情况,使用maven:
首先,在pom.xml中配置库的地址:
osc-repo
http://maven.oschina.net/content/groups/public/
public-repo2
http://repo2.maven.org/maven2/
jitpack.io
https://jitpack.io
Jitpack.io Repository
true
true
其中主要是jitpack.io这个库地址的配置,其他都是我自己配置的。这个配置允许从它的库中下载这个依赖,然后加上依赖的配置:
com.github.kamaladafrica
axon-cdi
1.0-SNAPSHOT
还有几个依赖,是cdi扩展:apache-deltaspike,用于事务控制,axon-cdi也使用了deltaspike,也要加上:
org.apache.deltaspike.core
deltaspike-core-api
1.6.0
compile
org.apache.deltaspike.core
deltaspike-core-impl
1.6.0
runtime
org.apache.deltaspike.modules
deltaspike-jpa-module-api
1.6.0
compile
org.apache.deltaspike.modules
deltaspike-jpa-module-impl
1.6.0
axon-cdi-quickstart-master这个例子使用deltaspike的启动和停止,直接运行的,但我的工程是个web工程(我把addressbook的api和webui工程整合到了一个工程里面),所以,需要使用容器中的CDI环境。axon-cdi使用的是cdi-api 1.1版本,所以必须使用JavaEE7应用服务器,我用的是WildFly8.2.0.Final。之前不清楚这个情况,在tomee1.7.4上部署,总没有效果,因为tomee目前只支持javaee6.
还有deltaspike-jpa-xxxx是cdi扩展,可以使用@Transactional注解来控制数据库事务。使用这种方式控制事务,需要注意EntityManager的生成方式:EntityManager的producer应该这样:
@ApplicationScoped
public class EntityManagerProducer {
@PersistenceUnit
private EntityManagerFactory entityManagerFactory;
@Produces
@Default
@RequestScoped
public EntityManager create()
{
return this.entityManagerFactory.createEntityManager();
}
public void dispose(@Disposes @Default EntityManager entityManager)
{
if (entityManager.isOpen())
{
entityManager.close();
}
}
}
使用EntityManagerFactory和@PersistenceUnit注解,在使用EntityManager的地方,应该使用@Inject注解,而不要直接使用@PersistenceContext注解,这种方式参考了官方文档。这样配置后,就可以在方法上直接加入@Transactional来指定事务控制了。
还有,我使用的是GenricJPARepository,例子原本用的是EventSourcedRepository,按照axon的要求聚合根必须使用jpa注解过的才可以,否则它不会保存数据到contactentry表