web-dev-qa-db-ja.com

Jersey 2でのデフォルトのプロバイダー/ MessageBodyWritersの使用

Jerseyから始めて、私は最新のJerseyドキュメンテーション ' building response 'の簡単な例を再現しようとしています。この部分は、私が理解している限り、ResponseおよびResponseBuilderを使用して、応答コンテンツのEntity<T>と組み合わせて応答を簡単に返す方法を示す必要があります。

現在、ドキュメントにはいくつかのデータタイプがデフォルトでサポートされていると記載されています(ここでは ' Representations and Java types ')。それらのStringプライム、あらゆるメディアタイプに一致.

私が試したすべてのバリエーションのうち、以下が最も簡単です。

@POST
public Response post() {
    URI createdUri;
    try {
        createdUri = new URI("http://test.lan");
    } catch (final URISyntaxException e) {
        throw new WebApplicationException(e);
    }

    return Response.created(createdUri).entity(Entity.text("someContent")).build();
}

リクエストを呼び出すと、常に同じエラー(以下の完全なスタックトレース)が発生します:org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=text/plain, type=class javax.ws.rs.client.Entity, genericType=class javax.ws.rs.client.Entity.

このエンティティのジェネリック型に適したプロバイダーが見つからなかったと言っています。ただし、StringはOOTBをサポートする必要がありますか?

StringMessageProviderはおそらくこのプロバイダーのJersey 1実装であり、Jersey 2ライブラリーで見つけた最も近い関連クラスはjersey-commonのorg.glassfish.jersey.message.internalのクラスです。多くのプロバイダーの中には、StringMessageProviderがあります。

私は問題を調べましたが、カスタムプロバイダーを誤って使用しようとしたときにこれを取得する人はたくさんいますが、デフォルトのOOTBプロバイダーが機能していないことについては何も見つかりませんでした。

私は自分のライブラリを確認しましたが、今のところ、私のpomには次のような依存関係があります(特に)。

  • ジャージーコンテナーサーブレットコア
  • ジャージークライアント
  • ジャージコモン
  • ジャージーサーバー

オンラインで調べましたが、必要なのはこれだけですが、jar内にStringおよびJAXB/JSONの適切なプロバイダークラスが確実に見つかっていません。

環境

  • Mavenプロジェクト
  • tomcat servlet-api 6.0.29
  • 上記のすべてのジャージライブラリのバージョン2.6
  • 日食ケプラー
  • Tomcat6 mavenプラグインを使用して埋め込まれたTomcatを実行する(これまでのところうまくいきます)

テストに使用されるフィドラーリクエスト

POST HTTP/1.1
User-Agent: Fiddler
Host: 127.0.0.1
Content-Length: 0

そして再びいくつかのバリエーションを試しました。

完全なスタックトレース

06-Jan-2015 21:13:54 org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor aroundWriteTo
SEVERE: MessageBodyWriter not found for media type=text/plain, type=class javax.ws.rs.client.Entity, genericType=class javax.ws.rs.client.Entity.
06-Jan-2015 21:13:54 org.Apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet TestService threw exception
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=text/plain, type=class javax.ws.rs.client.Entity, genericType=class javax.ws.rs.client.Entity.
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.Java:247)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.Java:162)
    at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.Java:103)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.Java:162)
    at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.Java:88)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.Java:162)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.Java:1154)
    at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.Java:571)
    at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.Java:378)
    at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.Java:368)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.Java:262)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.Java:271)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.Java:267)
    at org.glassfish.jersey.internal.Errors.process(Errors.Java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.Java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.Java:267)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.Java:319)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.Java:236)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.Java:1028)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.Java:373)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.Java:381)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.Java:344)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.Java:219)
    at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:290)
    at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:206)
    at org.Apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.Java:233)
    at org.Apache.catalina.core.StandardContextValve.invoke(StandardContextValve.Java:191)
    at org.Apache.catalina.core.StandardHostValve.invoke(StandardHostValve.Java:127)
    at org.Apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.Java:102)
    at org.Apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.Java:109)
    at org.Apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.Java:293)
    at org.Apache.coyote.http11.Http11Processor.process(Http11Processor.Java:859)
    at org.Apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.Java:602)
    at org.Apache.Tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.Java:489)
    at Java.lang.Thread.run(Thread.Java:662)

編集

同じエラー(application/jsonの場合)が発生し、クラスに@XmlRootElementで注釈を付け、Jerseyのドキュメントに従ってメソッドでそれを返そうとしました。

@GET
@Produces(MediaType.APPLICATION_JSON) 
public Foo sampleFoo() {
    Foo foo = new Foo();

    return foo;
}

ここで、Fooには@XmlRootElementの注釈が付けられています。

また、依存関係としてjersey-media-json-jacksonを追加しました。これには、明示的なJSONJaxbプロバイダーが含まれていることがわかります。しかし、なんとか拾われていないようです。

10
Mark Tielemans

創刊:

_javax.ws.rs.client.Entity_ はクライアント側のクラスです。 JAX-RS仕様は、サーバー側での使用については何も述べていません。しかし、私は多くの異なるテストで、結果が(少なくともジャージーで)見ているものと同じになることを確認できます。 Resteasyでは、Entity.toString()を送信するだけです

これはResteasyとJerseyのどちらでも機能しないため、バグだとは言いませんが、次のように使用例を示しているJerseyのドキュメントに誤りがある可能性があります。

_@POST
@Consumes("application/xml")
public Response post(String content) {
  URI createdUri = ...
  String createdContent = create(content);
  return Response.created(createdUri)
                         .entity(Entity.text(createdContent)).build();
}
_

上記も私にとって失敗しました。しかし、あなたは言っても間違っていません

...いくつかのデータ型はデフォルトでサポートされています

彼らはあるとして。サンプルを機能させるには、Entity.text("someContent")を単に_"someContent"_に変更します

_return Response.created(createdUri).entity("someContent").build();
_

そして、完全を期すために、 クライアント側の使用法 は次のようになります

_Response response = webTarget.request().post(Entity.text("Hello World"));
_

うまくいきます。

2番目の問題:

Jersey 2.9まで(私はそう思います)、_jersey-media-json-jackson_モジュールは自動構成されません。したがって、2.6では、_web.xml_またはApplicationサブクラスのパッケージスキャンを介して構成をセットアップする必要があります。どちらの方法でも、_web.xml_が必要です。すでに述べたように、Tomcat 6がそうである2.xサーブレット環境に関しては here です。

サーブレット2.5環境では、Webアプリケーションのweb.xmlデプロイメント記述子ファイルでJerseyコンテナサーブレットを明示的に宣言する必要があります。

したがって、JSONプロバイダークラスをスキャンするには、_jersey.config.server.provider.packages_ init-paramでパッケージを指定する必要があります。 web.xmlの例は次のようになります

_<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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_2_5.xsd">
    <servlet>
        <servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>
            org.glassfish.jersey.servlet.ServletContainer
        </servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>
                thepackage.of.your.resources,
                org.codehaus.jackson.jaxrs      <!-- Jackson providers -->
            </param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey Web Application</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>
</web-app>
_

Applicationサブクラス(ResourceConfigの拡張元)を使用することもできます。 _web.xml_で指定するだけです。設定例は次のようになります

_public class MyApplication extends ResourceConfig {  
    public MyApplication() {
        register(JacksonFeature.class);
        packages("thepackage.of.your.resources");
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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_2_5.xsd">
    <servlet>
        <servlet-name>MyApplication</servlet-name>
        <servlet-class>
            org.glassfish.jersey.servlet.ServletContainer
        </servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>jersey2.Tomcat6.MyApplication</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>MyApplication</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>
</web-app>
_

注:これらはすべて、Eclipseを使用する以外に、同じ環境に対してテストされました。 Netbeansを使用していますが、違いはありません。また、私が必要とした唯一のMaven依存関係は

_<dependencies>
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet-core</artifactId>
        <version>${jersey.version}</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>${jersey.version}</version>
    </dependency>
</dependencies>

<jersey.version>2.6</jersey.version>
_

別のメモでは、開発を簡略化するために、次の座標で単純なMavenアーキタイプを作成しました

_GroupId:     org.glassfish.jersey.archetypes
ArtifactId:  jersey-quickstart-webapp
Version:     2.6
_

Maven Archetypeからの新しいプロジェクトの作成 も確認できます。

23
Paul Samsotha

私の場合、jersey-media-json-jackson依存関係を追加しました。それは私のために働いた。

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.20</version>
</dependency>
1
Raghavendra b

テキスト/プレーン形式に関しては、これは機能しますか?

return Response.created(createdUri).type(MediaType.TEXT_PLAIN).entity("someContent").build();

JSON出力の場合、これらの依存関係があります

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>

また、jaxb実装。何でもします、私は使います

    <dependency>
        <groupId>com.Sun.xml.bind</groupId>
        <artifactId>jaxb-impl</artifactId>
    </dependency>

また、オブジェクトマッパープロバイダーを定義しますが、それが必要であるかどうかは100%わかりません(カスタマイズする場合を除きます)。

import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;

@Provider
public class ObjectMapperProvider implements ContextResolver<ObjectMapper> {
    ObjectMapper mapper;

    public ObjectMapperProvider() {
        mapper = new ObjectMapper();
        mapper.configure( SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false );
        mapper.configure( SerializationFeature.INDENT_OUTPUT, true );
        mapper.configure( SerializationFeature.WRITE_NULL_MAP_VALUES, true );
        mapper.configure( SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, true );
        mapper.setAnnotationIntrospector( new JaxbAnnotationIntrospector(TypeFactory.defaultInstance()) );
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return mapper;
    }
}

また、Jackson機能を登録する必要があると思います。

@ApplicationPath("")
public class Application extends ResourceConfig {
    public Application() {
        register( JacksonFeature.class );
    }
}

これはすべてJersey 2.11を使用して構成されていることに注意してください。

1
Don Bottstein