ぺーぺーSEのブログ

備忘録・メモ用サイト。

Jersey-Spring3でHello World

Jersey2.8とSpring3でサンプルアプリを作成してみる。
Jersey2.8はJavaEE7のJAX-RS2.0準拠。

下記コマンドでプロジェクト作成。

mvn archetype:generate
    -DarchetypeGroupId=org.codehaus.mojo.archetypes
    -DarchetypeArtifactId=webapp-javaee7
    -DarchetypeVersion=1.1
    -DarchetypeRepository=https://nexus.codehaus.org/content/repositories/releases/
    -DgroupId=jp.sample
    -DartifactId=JerseySpring3Sample
    -Dversion=1.0.0

POMを下記のように編集。

■pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>jp.sample</groupId>
    <artifactId>JerseySpring3Sample</artifactId>
    <version>1.0.0</version>
    <packaging>war</packaging>

    <name>JerseySpring3Sample</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <jersey.version>2.8</jersey.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.ext</groupId>
            <artifactId>jersey-spring3</artifactId>
            <version>${jersey.version}</version>
        </dependency> 
        <dependency>
            <groupId>org.glassfish.jersey.connectors</groupId>
            <artifactId>jersey-apache-connector</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.3</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>JerseySpring3Sample</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

「src/main」配下に「resources」ディレクトリ作成。
「src/main/webapp/index.html」ディレクトリ削除。
「src/main/webapp」配下に「WEB-INF」ディレクトリ作成。
「src/main/webapp」配下に「web.xml」ファイル作成。



■jp.sample.resource.SampleResource

package jp.sample.resource;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Path("")
@Component
public class SampleResource {
    
    @Autowired
    @Qualifier("client")
    private Client client;

    @Path("hello")
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "Hello !";
    }

    @Path("google")
    @GET
    @Produces(MediaType.TEXT_HTML)
    public String getGoogle() {
        WebTarget target = client.target("https://www.google.co.jp");
        return target.request().get().readEntity(String.class);
    }
}



■jp.sample.application.SampleApplication

package jp.sample.application;

import jp.sample.resource.SampleResource;

import org.glassfish.jersey.server.ResourceConfig;

public class SampleApplication extends ResourceConfig {

    public SampleApplication () {
        register(SampleResource.class);
    }
}

後述のweb.xmlの①の場合のみ使用。



■jp.sample.rest.client.ClientFactory

package jp.sample.rest.client;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;

import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;

public class ClientFactory {

    private Client client;

    public ClientFactory() {
        ClientConfig cc = new ClientConfig();
        cc.connectorProvider(new ApacheConnectorProvider());
        cc.property(ClientProperties.PROXY_URI, "-");
        cc.property(ClientProperties.PROXY_USERNAME, "-");
        cc.property(ClientProperties.PROXY_PASSWORD, "-");
        cc.property(ClientProperties.CONNECT_TIMEOUT , 2000);
        client = ClientBuilder.newClient(cc);
    }
    
    public Client getClient() {
        return this.client;
    }
}

JAX-RS2.0からRest Client追加されたのでちょろっと使ってみた。
あと、プロキシ環境下の設定方法を試した。
(Jersey2.6前後くらいでやり方が変わってるっぽい?)
SpringのapplicationContext.xmlでbean定義してSampleResourceのフィールドへインジェクションしてる。



■commons-logging.properties

org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger

なんか依存ライブラリでCommonsLogging使ってるぽいからとりあえず。



log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

  <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
    <param name="Target" value="System.out" />
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="[%d{yyyy/MM/dd HH:mm:ss}][%-5p][%t][%c{1}] %m%n" />
    </layout>
  </appender>
  
  <root>
    <priority value="ERROR" />
    <appender-ref ref="CONSOLE" />
  </root>

</log4j:configuration>



■applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.0.xsd">

  <context:annotation-config />
  <context:component-scan base-package="jp.sample" />
  
  <!-- Rest Client作成用ファクトリクラスをbean定義 -->
  <bean id="clientFactory" class="jp.sample.rest.client.ClientFactory" />
  
  <!-- 上記ファクトリクラスから取得するオブジェクトのbean定義 -->
  <bean id="client" factory-bean="clientFactory" factory-method="getClient" />

</beans>

ファクトリクラスを使ったオブジェクト生成およびbean定義もやってみた。



■web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

  <module-name>Jersey Spring Web Application</module-name>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>

  <servlet>
    <servlet-name>Jersey Spring Web Application</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

    <!-- ①Applicationクラスを作成する方法の場合
    <init-param>
      <param-name>javax.ws.rs.Application</param-name>
      <param-value>jp.sample.application.SampleApplication</param-value>
    </init-param>
     -->
    <!-- ②Applicationクラスを使用せず、パッケージ指定でリソースクラスやエンティティプロバイダ、Exceptionマッパをスキャンする場合(サブパッケージはスキャンしない)
    <init-param>
      <param-name>jersey.config.server.provider.packages</param-name>
      <param-value>jp.sample.resource</param-value>
    </init-param>
    <init-param>
      <param-name>jersey.config.server.provider.scanning.recursive</param-name>
      <param-value>false</param-value>
    </init-param>
     -->
    <!-- ③Applicationクラスを使用せず、クラス指定でリソースクラスやエンティティプロバイダ、Exceptionマッパを指定する場合 -->
    <init-param>
      <param-name>jersey.config.server.provider.classnames</param-name>
      <param-value>jp.sample.resource.SampleResource</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>Jersey Spring Web Application</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>

</web-app>

以上でサンプル実装完了。
サンプルを起動した後ブラウザで「http://[FQDN]:8080/JerseySpring3Sample/hello」へアクセスすると「Hello !」表示される。
「http://[FQDN]:8080/JerseySpring3Sample/google」へアクセスすると(文字化けしまくった上にまったく使えない)Googleトップページが表示される。

■参考
Jersey2.8 Guide
https://jersey.java.net/documentation/2.8/index.html

web.xmlのinit-paramの書き方
https://jersey.java.net/documentation/latest/deployment.html#deployment.servlet

jersey-spring3
https://jersey.java.net/documentation/latest/spring.html

jersey-spring3のサンプル
https://github.com/jersey/jersey/tree/2.8/examples/helloworld-spring-webapp

Jersey Client
https://jersey.java.net/documentation/latest/client.html

rest-clientのproxy設定方法
http://qiita.com/opengl-8080/items/ca33230cb8df1148fb6f

Jersey-Spring3,Client等
http://www.codingpedia.org/ama/restful-web-services-example-in-java-with-jersey-spring-and-mybatis/