kagamihogeの日記

kagamihogeの日記です。

spring-bootのspring-data-jpaでJTAにAtomikosを使用する

spring-bootでspring-data-jpaを使う場合JTAはHIkariCPが特に何も設定しなくても使われる。通常はこれで何ら問題は無いが以下ではJTAをAtomikosに変更するやり方のメモ。

pom.xml

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
    </parent>

    <properties>
        <java.version>10.0</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jta-atomikos</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
        </dependency>
    </dependencies>

現時点(2018/08/21)最新版の2.0.4.RELEASEだとspring-data-jpaが動作しなかったので2.0.3にしている。

javax.xml.bindについては ClassNotFoundException for javax.xml.bind.JAXBException with Spring Boot when swich to Java 9 - Stack Overflow を参照。

JTAをAtomikosに変更する場合は依存性にspring-boot-starter-jta-atomikosを追加するだけで良い。

プロパティ

application.propertiesで以下のように設定する。例えば、以下によりcom.atomikos.icatch.max_timeoutを変更できる。

spring.jta.atomikos.properties.max_timeout=312345

プロパティ一覧についてはAtomikosProperties (Spring Boot Docs 2.0.4.RELEASE API) を参照。

ソースコード

動作確認用のソースコード。HelloWorldレベルのことしかやってない。テーブルについては作ってあるもんとする。

package kagamihoge.springdatajpa;

import java.util.Optional;

import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Hello world!
 *
 */
@SpringBootApplication
public class App  implements CommandLineRunner{
    public static void main(String[] args) {
        SpringApplication.run(App.class, args).close();
    }
    
    @Autowired
    UserRepository userRepository;
    
    @Transactional
    @Override
    public void run(String... args) throws Exception {
        Optional<User> user = userRepository.findById(1L);
        System.out.println(user.get().getEmail());
    }
}
package kagamihoge.springdatajpa;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "users")
public class User {
    @Id
    private Long userId;
    private String username;
    private String password;
    private String email;
    public Long getUserId() {
        return userId;
    }
    public void setUserId(Long userId) {
        this.userId = userId;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
}
package kagamihoge.springdatajpa;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends CrudRepository<User, Long> {
}
spring.datasource.url=jdbc:postgresql://192.168.10.23:5432/testdb
spring.datasource.username=postgres
spring.datasource.password=xxxx