web-dev-qa-db-ja.com

ジャージーを使用したJAXWS RS-コレクション、マップなどを返す

私は使用していますJersey 2.

私のWSエンドポイントクラス:

@Path("/employees")
public class EmployeeWSEndpoint {

    @Context
    Request request;

    @GET
    @Path("/allEmployees")
    @Produces(MediaType.APPLICATION_JSON)
    public List<Employee> getAllEmployees() {

        System.out.println("In EmployeeWSEndpoint.getAllEmployees()");

        EmployeeService employeeService = new EmployeeServiceImpl();
        return employeeService.getAllEmployees();
    }

    @GET
    @Path("/allDept")
    @Produces(MediaType.APPLICATION_JSON)
    public List<String> getAllDept() {

        System.out.println("In EmployeeWSEndpoint.getAllDept()");

        List<String> deptNames = new ArrayList<>();
        deptNames.add("CoE");
        deptNames.add("iLabs");

        return deptNames;
    }

    @GET
    @Path("/allDeptPOJO")
    @Produces(MediaType.APPLICATION_JSON)
    public TempPOJO getAllDeptPOJO() {

        System.out.println("In EmployeeWSEndpoint.getAllDeptPOJO");

        TempPOJO tempPOJO = new TempPOJO();

        return tempPOJO;
    }
}

従業員POJO:

public class Employee {

    private int id;
    private String firstName;
    private String middleName;
    private String lastName;
    private Date dob;
    private int deptId;

    public Employee() {

    }

    public Employee(String firstName, String middleName, String lastName,
            Date dob, int deptId) {
        this.firstName = firstName;
        this.middleName = middleName;
        this.lastName = lastName;
        this.dob = dob;
        this.deptId = deptId;
    }

    public Employee(int id, String firstName, String middleName,
            String lastName, Date dob, int deptId) {
        this.id = id;
        this.firstName = firstName;
        this.middleName = middleName;
        this.lastName = lastName;
        this.dob = dob;
        this.deptId = deptId;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getMiddleName() {
        return middleName;
    }

    public void setMiddleName(String middleName) {
        this.middleName = middleName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Date getDob() {
        return dob;
    }

    public void setDob(Date dob) {
        this.dob = dob;
    }

    public int getDeptId() {
        return deptId;
    }

    public void setDeptId(int deptId) {
        this.deptId = deptId;
    }

    @Override
    public String toString() {
        return firstName + " " + middleName + " " + " " + lastName;
    }
}

一時的なPOJO:

public class TempPOJO {

    private List<String> deptNames;

    public List<String> getDeptNames() {

        deptNames = new ArrayList<>();
        deptNames.add("CoE");
        deptNames.add("iLabs");

        return deptNames;
    }

    public void setDeptNames(List<String> deptNames) {
        this.deptNames = deptNames;
    }

}

さまざまなメソッドの出力を一覧表示します。

allEmployees

[{"deptId":1,"dob":"1978-06-19","firstName":"Garfield","id":0,"lastName":"Arbuckle","middleName":"John"},{"deptId":1,"dob":"1946-07-07","firstName":"John","id":0,"lastName":"Rambo","middleName":"R"}]

/ allDept

In EmployeeWSEndpoint.getAllDept()
Oct 01, 2013 3:31:08 PM org.glassfish.jersey.server.ServerRuntime$Responder mapException
WARNING: WebApplicationException cause:
javax.xml.bind.MarshalException
 - with linked exception:
[Exception [EclipseLink-25003] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.Eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred marshalling the object
Internal Exception: Exception [EclipseLink-25007] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.Eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor for class Java.lang.String was not found in the project.  For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.]
    at org.Eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.Java:403)
    at org.Eclipse.persistence.jaxb.rs.MOXyJsonProvider.writeTo(MOXyJsonProvider.Java:808)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.Java:243)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.Java:230)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.Java:149)
    at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.Java:103)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.Java:149)
    at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.Java:88)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.Java:149)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.Java:1139)
    at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.Java:562)
    at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.Java:357)
    at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.Java:347)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.Java:258)
    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:318)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.Java:235)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.Java:983)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.Java:359)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.Java:372)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.Java:335)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.Java:218)
    at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:305)
    at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
    at org.Apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.Java:222)
    at org.Apache.catalina.core.StandardContextValve.invoke(StandardContextValve.Java:123)
    at org.Apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.Java:472)
    at org.Apache.catalina.core.StandardHostValve.invoke(StandardHostValve.Java:171)
    at org.Apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.Java:99)
    at org.Apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.Java:947)
    at org.Apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.Java:118)
    at org.Apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.Java:408)
    at org.Apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.Java:1009)
    at org.Apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.Java:589)
    at org.Apache.Tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.Java:310)
    at Java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at Java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at Java.lang.Thread.run(Unknown Source)
Caused by: Exception [EclipseLink-25003] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.Eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred marshalling the object
Internal Exception: Exception [EclipseLink-25007] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.Eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor for class Java.lang.String was not found in the project.  For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.
    at org.Eclipse.persistence.exceptions.XMLMarshalException.marshalException(XMLMarshalException.Java:97)
    at org.Eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.Java:911)
    at org.Eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.Java:848)
    at org.Eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.Java:401)
    ... 41 more
Caused by: Exception [EclipseLink-25007] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.Eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor for class Java.lang.String was not found in the project.  For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.
    at org.Eclipse.persistence.exceptions.XMLMarshalException.descriptorNotFoundInProject(XMLMarshalException.Java:139)
    at org.Eclipse.persistence.internal.oxm.Context$ContextState.getSession(Context.Java:143)
    at org.Eclipse.persistence.oxm.XMLContext$XMLContextState.getSession(XMLContext.Java:787)
    at org.Eclipse.persistence.oxm.XMLContext$XMLContextState.getSession(XMLContext.Java:1)
    at org.Eclipse.persistence.internal.oxm.Context.getSession(Context.Java:451)
    at org.Eclipse.persistence.oxm.XMLContext.getSession(XMLContext.Java:356)
    at org.Eclipse.persistence.oxm.XMLContext.getSession(XMLContext.Java:1)
    at org.Eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.Java:568)
    at org.Eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.Java:1096)
    at org.Eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.Java:869)
    ... 43 more

/ allDeptPOJO

{"deptNames":["CoE","iLabs"]}

私はいくつか持っていますクエリ

  1. Jersey 2.3以降、POJOにはアノテーション「XmlRootElement」は必要ないと思います。まだ行っていませんが、呼び出しは機能します。確認してください
  2. Pojo(Employee)のリストまたはリストを持つpojoの場合、応答は適切ですが、List、Mapなどの場合は失敗します(基本的に、Javaタイプ)の場合)-なぜですかこれはそうですか?それがEmployeeで機能する場合、なぜJavaタイプで機能しないのですか?XmlAdapterを作成する必要がありますか?

:ほとんどの場合、JSONでの応答が必要です。

Jacksonを使用するようにweb.xmlを変更する:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://Java.Sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://Java.Sun.com/xml/ns/javaee http://Java.Sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <display-name>Jersey</display-name>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>

    <servlet>
        <servlet-name>Jersey REST Service</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>com.ws.jaxrs.jersey</param-value>
        </init-param>
        <init-param>
            <param-name>jersey.config.disableMoxyJson.server</param-name>
            <param-value>true</param-value>
        </init-param>

        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>com.ws.jaxrs.jersey;org.codehaus.jackson.jaxrs</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Jersey REST Service</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>


</web-app>

次の例外が発生しました:

In EmployeeWSEndpoint.getAllDept()
Nov 07, 2013 10:04:12 AM org.Apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Jersey REST Service] in context with path [/Jersey] threw exception [org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json, type=class Java.util.ArrayList, genericType=Java.util.List<Java.lang.String>.] with root cause
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json, type=class Java.util.ArrayList, genericType=Java.util.List<Java.lang.String>.
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.Java:227)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.Java:149)
    at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.Java:103)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.Java:149)
    at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.Java:88)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.Java:149)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.Java:1139)
    at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.Java:562)
    at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.Java:357)
    at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.Java:347)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.Java:258)
    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:318)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.Java:235)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.Java:983)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.Java:359)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.Java:372)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.Java:335)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.Java:218)
    at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:304)
    at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
    at org.Apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.Java:224)
    at org.Apache.catalina.core.StandardContextValve.invoke(StandardContextValve.Java:169)
    at org.Apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.Java:472)
    at org.Apache.catalina.core.StandardHostValve.invoke(StandardHostValve.Java:168)
    at org.Apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.Java:100)
    at org.Apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.Java:929)
    at org.Apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.Java:118)
    at org.Apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.Java:405)
    at org.Apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.Java:964)
    at org.Apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.Java:515)
    at org.Apache.Tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.Java:302)
    at Java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at Java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at Java.lang.Thread.run(Unknown Source)
14

ジャクソンは今のところ私にとって最良の解決策です。

JacksonをJSONプロバイダーとして使用するには、jersey-media-json-jacksonモジュールをpom.xmlファイルに追加する必要があります。

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.7</version>
</dependency>

注:自動検出機能は機能しません。

Jackson JSON機能を有効にしてクライアントを構築する:

final Client client = ClientBuilder.newBuilder()
                    .register(JacksonFeature.class)
                    .build();

Jackson JSON機能を有効にしてJAX-RSサーバーアプリケーションを作成する:

final Application application = new ResourceConfig()
                              .packages("my.rest.package")
                              .register(JacksonFeature.class);

公式も確認してください Jersey json-jacksonの例

別のJSONプロバイダーを使用する

ジャージがデフォルトのJSONプロバイダーとしてMOXyを採用する理由はわかりませんが、それは明らかに悪い考えです。

あなた(そして私と他の人)が経験している問題は、MOXyビーイングの結果です 単純なJavaタイプ (文字列のような)のコレクションをマップすることができません-それはばかげていますimho。他のプロバイダー( jackson など)にはこの問題がないため、切り替えは間違いなく役立ちます。

これが私がしたことです:

  1. ジャージーnotにMOXyを使用するように指示します。これをweb.xmlに追加します。

    <init-param>
        <param-name>jersey.config.disableMoxyJson.server</param-name>
        <param-value>true</param-value>
    </init-param>
    
  2. あなたのpomにジャクソンを追加します。このようなことはします:

    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-jaxrs</artifactId>
        <version>1.9.12</version>
    </dependency>
    
  3. ジャージーにジャクソンジャクソンパッケージをスキャンするように伝えます。 jacksonが提供するjsonプロバイダーを検索(および使用)します。

    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>com.example.your.package;org.codehaus.jackson.jaxrs</param-value>
    </init-param>
    
7
sne11ius

注:私は EclipseLink JAXB(MOXy) リードおよび JAXB(JSR-222) エキスパートグループのメンバー。

発生している例外は、MOXyのMOXyJsonProviderのバグによるものです。 MOXyJsonProviderは、JAX-RSインターフェースMessageBodyReader/MessageBodyWriterの実装です。別のプロバイダーが処理できるように、isWriteableメソッドを変更してList<String>がfalseを返すようにし、falseを返すようにしました。

また、このサポートをMOXyに追加するために、次の拡張リクエストを開きました。

6
bdoughan

RestEasyをJAX-RS実装として使用できます

GlassFish4は、JAX-RSの実装としてJersey/MOXyを使用します。単純なJavaタイプ(文字列など)のコレクションをJSONにマッピングすることに問題があります https://bugs.Eclipse.org/bugs/show_bug.cgi?id=41772

WildFlyとJBossはJAX-RSの実装としてRestEasy/Jacksonを使用しており、マッピングに問題はありません。

Javaアプリケーションサーバー(WildFly(JBoss)、GlassFish、Tomcatなど)では、Jerseyの代わりにRestEasyを使用できます。

置き換えるだけ:

    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency>

と:

    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-servlet-initializer</artifactId>
        <version>3.0.7.Final</version>
        <scope>compile</scope>
    </dependency>        
    <dependency>
       <groupId>org.jboss.resteasy</groupId>
       <artifactId>resteasy-jaxrs</artifactId>
       <version>3.0.7.Final</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jackson-provider</artifactId>
        <version>3.0.7.Final</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jaxb-provider</artifactId>
        <version>3.0.7.Final</version>
        <scope>compile</scope>
    </dependency>

それは私のために働いています。

ポーランドのルブリンからよろしくお願いします:)

2
kinjelom

List<String>オブジェクトを返すのと同じ問題がありました。私はそれをRestStringListクラスでラップしました。それは機能します。これらをもっとやることがあれば、ジャクソンに切り替えるかもしれません。

import Java.io.Serializable;
import Java.util.ArrayList;
import Java.util.List;

public class RestStringList implements Serializable {
    private static final long serialVersionUID = 1L;

    private List<String> stringList = null;

    public RestStringList() {
        this.stringList = new ArrayList<String>();
    }

    public void setStringList(List<String> stringList) {
        this.stringList = new ArrayList<String>(stringList);
    }

    public List<String> getStringList() {
        return stringList;
    }

    public String toString() {
        return "{ strings=" + stringList + " }";
    }
}
0