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の適切なプロバイダークラスが確実に見つかっていません。
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プロバイダーが含まれていることがわかります。しかし、なんとか拾われていないようです。
_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"));
_
うまくいきます。
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からの新しいプロジェクトの作成 も確認できます。
私の場合、jersey-media-json-jackson依存関係を追加しました。それは私のために働いた。
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.20</version>
</dependency>
テキスト/プレーン形式に関しては、これは機能しますか?
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を使用して構成されていることに注意してください。