---
title: 【翻訳 Spring Boot 1.2における"Bootiful" なJava EEサポート
tags: ["Java", "Java EE 7", "Spring Boot"]
categories: ["Programming", "Java", "org", "springframework", "boot"]
date: 2014-11-26T07:47:48Z
updated: 2014-11-26T07:47:48Z
---

PivotalのDeveloper AdvocateのJosh Long([@starbuxman](https://twitter.com/starbuxman))がSpring Boot 1.2とJava EEに関する面白い記事を書いていたので、[本人の許可をとって](https://twitter.com/starbuxman/status/537461010609606656)翻訳してみました。わりとナチュラルに訳したつもりです。

元記事: ["Bootiful" Java EE Support in Spring Boot 1.2](http://spring.io/blog/2014/11/23/bootiful-java-ee-support-in-spring-boot-1-2)

---

この記事では、Java EEを使っている人またはSpring Bootに移ろうとしている人の開発をより容易にする[Spring Boot 1.2](http://spring.io/projects/spring-boot)の_多くの_新機能を見ていきたいと思います。そしてデモしたいと思います。

これらのサポートはこれまでのSpringでも当然利用できるのですが、今回のSpring Boot 1.2を使用することでとびきり簡単になるということを言っておきたいです。

まず始めにサンプルプログラムをお見せします。説明はそれからです。

```java

package demo;

import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsTemplate;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import javax.jms.JMSException;
import javax.persistence.*;
import javax.transaction.Transactional;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.io.Serializable;
import java.util.Collection;
import java.util.logging.Logger;

@SpringBootApplication
public class Application {

    @Named
    public static class JerseyConfig extends ResourceConfig {

        public JerseyConfig() {
            this.register(GreetingEndpoint.class);
            this.register(JacksonFeature.class);
        }
    }

    @Named
    @Transactional
    public static class GreetingService {

        @Inject
        private JmsTemplate jmsTemplate;

        @PersistenceContext
        private EntityManager entityManager;

        public void createGreeting(String name, boolean fail) {
            Greeting greeting = new Greeting(name);
            this.entityManager.persist(greeting);
            this.jmsTemplate.convertAndSend("greetings", greeting);
            if (fail) {
                throw new RuntimeException("simulated error");
            }
        }

        public void createGreeting(String name) {
            this.createGreeting(name, false);
        }

        public Collection<Greeting> findAll() {
            return this.entityManager
                    .createQuery("select g from " + Greeting.class.getName() + " g", Greeting.class)
                    .getResultList();
        }

        public Greeting find(Long id) {
            return this.entityManager.find(Greeting.class, id);
        }
    }

    @Named
    @Path("/hello")
    @Produces({MediaType.APPLICATION_JSON})
    public static class GreetingEndpoint {

        @Inject
        private GreetingService greetingService;

        @POST
        public void post(@QueryParam("name") String name) {
            this.greetingService.createGreeting(name);
        }

        @GET
        @Path("/{id}")
        public Greeting get(@PathParam("id") Long id) {
            return this.greetingService.find(id);
        }
    }

    @Entity
    public static class Greeting implements Serializable {

        @Id
        @GeneratedValue
        private Long id;

        @Override
        public String toString() {
            return "Greeting{" +
                    "id=" + id +
                    ", message='" + message + '\'' +
                    '}';
        }

        private String message;

        public String getMessage() {
            return message;
        }

        public Greeting(String name) {
            this.message = "Hi, " + name + "!";
        }

        Greeting() {
        }
    }

    @Named
    public static class GreetingServiceClient {

        @Inject
        private GreetingService greetingService;

        @PostConstruct
        public void afterPropertiesSet() throws Exception {
            greetingService.createGreeting("Phil");
            greetingService.createGreeting("Dave");
            try {
                greetingService.createGreeting("Josh", true);
            } catch (RuntimeException re) {
                Logger.getLogger(Application.class.getName()).info("caught exception...");
            }
            greetingService.findAll().forEach(System.out::println);
        }
    }

    @Named
    public static class GreetingMessageProcessor {

        @JmsListener(destination = "greetings")
        public void processGreeting(Greeting greeting) throws JMSException {
            System.out.println("received message: " + greeting);
        }
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

```

ソースコードは以上です。あとはちょっとした[`application.properties`](https://github.com/joshlong/techtips/blob/master/examples/jaxrs-jta-jms-jpa-330-250-undertow/src/main/resources/application.properties)と[Mavenのビルドファイル](https://github.com/joshlong/techtips/blob/master/examples/jaxrs-jta-jms-jpa-330-250-undertow/pom.xml)があるだけで、
これらはオンラインで参照可能です。

JerseyとJAX-RS
------------------

この例では`GreetingEndpoint`で[Bootの新機能であるJAX-RS自動設定をデモしています](http://docs.spring.io/spring-boot/docs/1.2.0.BUILD-SNAPSHOT/reference/htmlsingle/#boot-features-jersey) (この場合、[Jersey 2.x](https://jersey.java.net/)を使っています) 。
めっちゃ簡単に動かせている点に注目していただきたいです！唯一面倒くさいのは`ResourceConfig`のサブクラスを作成して、Jerseyに登録するコンポーネントを知らせないといけない点ですね。

JTAによるグローバルトランザクション
----------------------------
[新たにサポートされたJTA自動設定](http://docs.spring.io/spring-boot/docs/1.2.0.BUILD-SNAPSHOT/reference/htmlsingle/#boot-features-jta)によるグローバルトランザクションもデモしています。JTAはX/Open XAプロトコルのためのJava APIで、(このプロトコルに :訳者注)準拠した複数のトランザクションリソース(メッセージキューやデータベース)を単一のトランザクションに参加させます。これを行うために、我々はスタンドアローンなJTAプロバイダーである[Atomikos](http://www.atomikos.com/)を使用しました。同様に、Bitronixも簡単に利用できます。両方とも適切なstarterを持ってくれば自動設定されるのです。この例では、`GreetingService`の中でJMSとJPAの処理がグローバルトランザクションの一部として機能しています。3つのトランザクションを生成し、3つめの処理をわざとロールバックさせています。これにより、2つのレコードがのJDBCの`javax.sql.DataSource`から取得され、2つのレコードが組み込みJMSの`javax.jms.Destination`に受信されていることがコンソールの出力から分かるでしょう。

組み込みWebサーバーUndertow
--------------------------------

この例ではApache Tomcat(デフォルト)の代わりにWildFly (RedHat製) アプリケーションサーバーが持つ*素晴らしい*[Undertow 組み込みHTTPサーバー](http://undertow.io/)を使用しています。Undertowを使うのは簡単でTomcatの代わりにJettyを使うのと同じように、(依存関係から :訳者注)`org.springframework.boot:spring-boot-starter-tomcat`を除き、`org.springframework.boot:spring-boot-starter-undertow`を追加するだけです!この対応はサードパーティのプルリクエストが元となっています。- Ivan Sopovサンクス！ GJ！

諸々
-------------
(Java標準で :訳者注)統一感を出すために、この例ではJSR 330も使用しています。JSR 330では、WebLogicのようなプロプライエタリなアプリケーションサーバーでも、Google GuiceやSpringのようなDIコンテナでも同じように使えるようにするためのアノテーション群が決められています。またJSR 250のアノテーション(Java EE 5の一部として定義されました)も使用しています。これは(Beanの :訳者注)ライフサイクルにフックするデモを見せるためです。

この例では、Spring Bootで自動設定された組み込みインメモリ[H2](http://www.h2database.com/html/main.html)の`javax.sql.DataSource`とa Spring Bootで自動設定された組み込みインメモリ[HornetQ](http://hornetq.jboss.org)の`javax.jms.ConnectionFactory`に依存しています. 
組み込みでないインスタンスに接続したければ、好きなものを直接Bean定義すればよいです。

*また*、この例では新しい`@SpringBootApplication`アノテーションを使っています。これは`@Configuration`と`@EnableAutoConfiguration`と`@ComponentScan`を一つにしたものです。ナイス！

デプロイ
----------
この例ではJava EEの有名どころなAPIを沢山使っていますが、結局のところただのSpring Bootアプリケーションなのです。つまりデフォルトで、`java -jar ee.jar`でアプリケーションを実行できますし、Herokuや[Cloud Foundry](http://cloudfoundry.org)といったプロセス中心の[platforms-as-a-service](http://en.wikipedia.org/wiki/Platform_as_a_service)に簡単にデプロイできます。
もしスタンドアローンなアプリケーションサーバー(Apache TomcaやWebSphereなど)にデプロイしたいのであれば、単純に`.war`に変換し、Servlet 3対応のコンテナにデプロイすれば良いです。

もしより古典的なアプリケーションサーバーにデプロイするなら、代わりにSpring Bootはサーバーの機能をうまく利用できます。例えば、極めてシンプルに、JNDIから[JMS `ConnectionFactory`](http://docs.spring.io/spring-boot/docs/1.2.0.BUILD-SNAPSHOT/reference/htmlsingle/#boot-features-jms-jndi),や[JDBC `DataSource`](http://docs.spring.io/spring-boot/docs/1.2.0.BUILD-SNAPSHOT/reference/htmlsingle/#boot-features-connecting-to-a-jndi-datasource) 、 [JTA `UserTransaction`](http://docs.spring.io/spring-boot/docs/1.2.0.BUILD-SNAPSHOT/reference/htmlsingle/#_using_a_java_ee_managed_transaction_manager)を取得できます。

Spring Boot 1.2: 選択肢 *と* パワー
--------------------------------------

個人的には、これらの沢山のAPIには疑問をもっています。*本当に*、分散マルチリソーストランザクションが必要でしょうか？今日の[分散化さされた世界においてグローバルトランザクションマネージャーを考えるのはアーキテクチャ的に臭いますね](http://www.eaipatterns.com/ramblings/18_starbucks.html)([リンク先の日本語訳](https://code.google.com/p/gregors-ramblings-ja/wiki/18_starbucks) :訳者注)。SpringにはMVC、REST、HATEOS、OAuth、WebSocketがサポートされた、よりリッチで統合されたSpring MVCベースのスタックがあるのに、*本当に*JAX-RSを使いますか？JPAはSQLベースの`javax.sql.DataSource`とやり取りするためのナイスなAPIであるけれど、Spring Dataのリポジトリ(JPAサポートはもちろん、Cassandra、MongoDB、Redis、CouchBaseなどなど沢山の代替テクノロジー_も_サポートしている)は多くのボイラーポレートをなくしてくれるし、一般的なケースで利用可能なシンプルなインタフェースを提供しています。だから、本当にこれらの全てが必要なんですか？これはあなたがよくやってるであろうし、いつも通りのように、「選択はあなた次第」なのです。これがこのリリースがクールな理由です。よりパワーを、より選択肢を。

他には？
----------

ぶっちゃけ*まだまだ*あります。 新機能がたくさんあります。全てのカバーをし始めるのもできなかったので、やりません。全てのスクープは[リリースノート](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-1.2-Release-Notes)を確認してください！

Spring Boot 1.2はもうすぐGAになります。[ちょっと試す](http://start.spring.io)のにちょうど良いタイミングです。[issueをあげて](https://github.com/spring-projects/spring-boot/issues)、 [質問して](http://stackoverflow.com/questions/tagged/spring-boot)ください！


---

という感じでJoshの記事を紹介してみました。Spring Boot 1.2面白いです。Java EEな方も是非お試しください。

Spring Boot 1.1の内容ですが、「はじめてのSpring Boot」もよろしく・・・


<a href="http://www.amazon.co.jp/%E3%81%AF%E3%81%98%E3%82%81%E3%81%A6%E3%81%AESpring-Boot%E2%80%95%E3%80%8CSpring-Framework%E3%80%8D%E3%81%A7%E7%B0%A1%E5%8D%98Java-BOOKS-%E4%BF%8A%E6%98%8E/dp/4777518655%3FSubscriptionId%3DAKIAJ7Y2FDFBWLT5HCQA%26tag%3Dikam-22%26linkCode%3Dsp1%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4777518655"><img src="http://ecx.images-amazon.com/images/I/51NngrEolCL._SL160_.jpg" title="はじめてのSpring Boot―「Spring Framework」で簡単Java (I/O BOOKS)"></a>
