hatenob

プログラムって分からないことだらけ

Wildflyで2つのデータソースでJPA使ったトランザクション

試したみたことのメモ。

試したこと

Wildflyで、同一のDBを指す、名前以外は同じの2つのデータソースを定義する。
JPA用にそれぞれのpersistence-unitを定義。
1つのEJB処理の中で2つのpersistence-unitに対して操作を行うとどうなるか?

試した理由

物理的には見ているリソースが同じでも、データソース違うからXAじゃないとダメなの?を確認するため。

試したソース

こんな感じの処理。

    @PersistenceContext(unitName = "primary")
    private EntityManager primary;

    @PersistenceContext(unitName = "secondary")
    private EntityManager secondary;

    public void register(Emp emp) {
        System.out.println(emp);
        Emp primaryCurrentEmp = primary.find(Emp.class, emp.getId());
        if (primaryCurrentEmp == null) {
            primary.persist(emp);
        } else {
            primaryCurrentEmp.setName(emp.getName());
        }

        Emp secondaryCurrentEmp = secondary.find(Emp.class, emp.getId());
        if (secondaryCurrentEmp == null) {
            secondary.persist(emp);
        } else {
            secondaryCurrentEmp.setName("secondary");
        }
    }

結果その1

起動はできたけど、実行したらsecondary.findのところでエラーになった。

Caused by: javax.transaction.SystemException: IJ000356: Failed to enlist: java.lang.Throwable: Unabled to enlist resource, see the previous warnings. tx=TransactionImple < ac, BasicAction: 0:ffffc0a83801:387ef9b6:54df6971:9 status: ActionStatus.ABORT_ONLY >
	at org.jboss.jca.core.connectionmanager.listener.TxConnectionListener$TransactionSynchronization.checkEnlisted(TxConnectionListener.java:848)

どうやら、Arjuna(トランザクションサービス)がデフォルトだと異なるデータソースの同一トランザクション使用をサポートしていないっぽい。
失敗。

結果その2

調べると、システムプロパティで無理やりできるっぽいので下をstandalone.xmlに追記する。

    <system-properties>
        <property name="com.arjuna.ats.jta.allowMultipleLastResources" value="true" />
    </system-properties>

結果、メソッドはちゃんと抜けた。
でも、update文が走ったのを最後に処理が止まった。デッドロックした?
DB見ると確かにロック状態になってるのがいる。ので、無理やり解除してエラーで落とす。
これも失敗。

結論

データソース違う場合はXAにすべきっぽい。

番外

データソース同じでpersistence-unitが違う、というのをやってみた。
こっちは大丈夫っぽい。