天天看點

使用CDI的axon架構搭建

一直在看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中配置庫的位址:

<repositories>
   		<repository>
            <id>osc-repo</id>
            <url>http://maven.oschina.net/content/groups/public/</url>
        </repository>
        <repository>
            <id>public-repo2</id>
            <url>http://repo2.maven.org/maven2/</url>
            </repository>
	   <repository>
	        <id>jitpack.io</id>
	        <url>https://jitpack.io</url>
	        <name>Jitpack.io Repository</name>
	        <releases>
	            <enabled>true</enabled>
	        </releases>
	        <snapshots>
	            <enabled>true</enabled>
	        </snapshots>
	    </repository>
    </repositories>
           

其中主要是jitpack.io這個庫位址的配置,其他都是我自己配置的。這個配置允許從它的庫中下載下傳這個依賴,然後加上依賴的配置:

<dependency>
      <groupId>com.github.kamaladafrica</groupId>
      <artifactId>axon-cdi</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
           

這個庫我自己是直接下載下傳的zip源代碼,自己安裝的,你也可以這樣搞。

還有幾個依賴,是cdi擴充:apache-deltaspike,用于事務控制,axon-cdi也使用了deltaspike,也要加上:

<dependency>
    <groupId>org.apache.deltaspike.core</groupId>
    <artifactId>deltaspike-core-api</artifactId>
    <version>1.6.0</version>
    <scope>compile</scope>
</dependency>

	<dependency>
	<groupId>org.apache.deltaspike.core</groupId>
	<artifactId>deltaspike-core-impl</artifactId>
	<version>1.6.0</version>
	<scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.apache.deltaspike.modules</groupId>
    <artifactId>deltaspike-jpa-module-api</artifactId>
    <version>1.6.0</version>
    <scope>compile</scope>
</dependency>

<dependency>
	<groupId>org.apache.deltaspike.modules</groupId>
	<artifactId>deltaspike-jpa-module-impl</artifactId>
	<version>1.6.0</version>
</dependency>
           

還有,axon-cdi自己有個例子,可以參照:axon-cdi-quickstart-master,同樣也在github上,然後根據這個例子的AxonConfiguration.java中的配置,自己修改一些自己使用的東西,入repository,主要是axon-cdi的@AutoConfigure注解,是幫助程式自動解析@CommandHandler、@EventHandler之類注解生成bean執行個體的。

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表