web-dev-qa-db-ja.com

Jersey JSON POJOサポートを使用するにはどうすればよいですか?

JSONでRESTfulリソースとして提供したいオブジェクトがあります。ジャージーのJSON POJOサポートを有効にしました(web.xmlで):

<servlet>  
    <servlet-name>Jersey Web Application</servlet-name>  
    <servlet-class>com.Sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>com.Sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>

    <load-on-startup>1</load-on-startup>  
</servlet>  

しかし、リソースにアクセスしようとすると、次の例外が発生します。

SEVERE: A message body writer for Java type, class com.example.MyDto, and MIME media type, application/json, was not found
SEVERE: Mapped exception to response: 500 (Internal Server Error)
javax.ws.rs.WebApplicationException
...

私がサービスを提供しようとしているクラスは複雑ではありません。すべてのパブリック最終フィールドとそれらすべてを設定するコンストラクターだけがあります。フィールドはすべて、文字列、プリミティブ、これに類似したクラス、またはそれらのリストです(一般的なList <T>の代わりにプレーンリストを使用しようとしましたが、使用できません)。誰が何を与えるのか知っていますか?ありがとう!

Java EE 6

ジャージー1.1.5

GlassFish 3.0.1

40
Nick

Jersey-jsonにはJAXB実装があります。この例外が発生する理由は、 Provider が登録されていないためです。具体的には MessageBodyWriter が登録されていないためです。プロバイダー内に適切なコンテキストを登録する必要があります。

@Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
    private final static String ENTITY_PACKAGE = "package.goes.here";
    private final static JAXBContext context;
    static {
        try {
            context = new JAXBContextAdapter(new JSONJAXBContext(JSONConfiguration.mapped().rootUnwrapping(false).build(), ENTITY_PACKAGE));
        } catch (final JAXBException ex) {
            throw new IllegalStateException("Could not resolve JAXBContext.", ex);
        }
    }

    public JAXBContext getContext(final Class<?> type) {
        try {
            if (type.getPackage().getName().contains(ENTITY_PACKAGE)) {
                return context;
            }
        } catch (final Exception ex) {
            // trap, just return null
        }
        return null;
    }

    public static final class JAXBContextAdapter extends JAXBContext {
        private final JAXBContext context;

        public JAXBContextAdapter(final JAXBContext context) {
            this.context = context;
        }

        @Override
        public Marshaller createMarshaller() {
            Marshaller marshaller = null;
            try {
                marshaller = context.createMarshaller();
                marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            } catch (final PropertyException pe) {
                return marshaller;
            } catch (final JAXBException jbe) {
                return null;
            }
            return marshaller;
        }

        @Override
        public Unmarshaller createUnmarshaller() throws JAXBException {
            final Unmarshaller unmarshaller = context.createUnmarshaller();
            unmarshaller.setEventHandler(new DefaultValidationEventHandler());
            return unmarshaller;
        }

        @Override
        public Validator createValidator() throws JAXBException {
            return context.createValidator();
        }
    }
}

これは、提供されたパッケージ名内の@XmlRegistryを検索します。これは、@XmlRootElement注釈付きPOJOを含むパッケージです。

@XmlRootElement
public class Person {

    private String firstName;

    //getters and setters, etc.
}

次に、同じパッケージにObjectFactoryを作成します。

@XmlRegistry
public class ObjectFactory {
   public Person createNewPerson() {
      return new Person();
   }
}

@Providerが登録されていると、Jerseyはリソースでのマーシャリングを促進する必要があります。

@GET
@Consumes(MediaType.APPLICATION_JSON)
public Response doWork(Person person) {
   // do work
   return Response.ok().build();
}
12
hisdrewness

JAXB注釈を使用する場合は、@XmlRootElementを使用できます(他の回答を参照)。

ただし、純粋なPOJOマッピングを好む場合は、次のことを行う必要があります(残念ながら、ドキュメントには書かれていません)。

  1. Jackson * .jarをクラスパスに追加します(@Vitali Bichovの説明どおり)。
  2. Web.xmlでcom.Sun.jersey.config.property.packages initパラメーターを使用している場合は、org.codehaus.jackson.jaxrsをリストに追加します。これにより、JerseyのスキャンリストにJSONプロバイダーが含まれます。
15
gamliela

これは私のためにそれをしました-ジャージー2.3.1

Web.xmlファイルで:

<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><my webapp packages>;org.codehaus.jackson.jaxrs</param-value>
</init-param>
</servlet>

Pom.xmlファイルで:

<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.3.1</version>
</dependency>
11
yann-h

here の指示に従いました。これは、ジャージーとジャクソンのPOJO(JAXBとは対照的に)の使用方法を示しています。 Jersey 1.12でも動作しました。

10
bytesmith

おそらくこれを既に理解しているはずですが、クラスパスにこれらのjackson jarを追加するだけです:jackson-core、jackson-jaxrs、jackson-mapper、およびjackson-xc

他の人が指摘したように、別の方法があるようです。これを「com.Sun.jersey.config.property.packages」パラメーターに追加します(Tomcatとweb.xmlを使用している場合):「org.codehaus.jackson.jaxrs」のように:

<init-param>
  <param-name>com.Sun.jersey.config.property.packages</param-name>
  <param-value>org.codehaus.jackson.jaxrs</param- value>
</init-param>

これを行うには、クラスパスに同じjackson jarも必要です。

3
ChrisO

最終フィールドを使用しているのはなぜですか?私はジャージを使用していますが、JAXBオブジェクト/ pojoがいくつかあり、リソースメソッドに@Produces( "application/json")の注釈を付けるだけで、すぐに使用できます。 web.xmlをいじる必要はありませんでした。ポジョに正しく注釈が付けられていることを確認してください。

これはシンプルなポジョです

package test;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class SampleJaxbObject {

    private String field1;

    private Integer field2;

    private String field3;

    public String getField1() {
        return field1;
    }

    public void setField1(String field1) {
        this.field1 = field1;
    }

    public Integer getField2() {
        return field2;
    }

    public void setField2(Integer field2) {
        this.field2 = field2;
    }

    public String getField3() {
        return field3;
    }

    public void setField3(String field3) {
        this.field3 = field3;
    }


}
3
Ricardo Riveros

Jersey 2.0は、MOXyとJacksonを使用したJSONのサポートを提供します。

JARがクラスパスに存在し、Jacksonサポートを機能を使用して有効にできる場合、MOXyサポートはデフォルトで有効になります。これはすべて、JSONバインディングに関するJersey 2.0ユーザーガイドの章で詳細に説明されています。

https://jersey.Java.net/documentation/latest/media.html#json

構成を必要とせずにMOXyサポートを追加するには、maven pom.xml

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-moxy</artifactId>
    <version>2.6</version>
</dependency>
3
Arun Gupta

これは初めてですが、クラスパスにjackson-all-1.9.0.jarを追加した後、POJOを使用することができました。

2
Vitali Bichov

次は私のために働いた。 Tomcat6で実行されているApache Felix(OSGi)で Jersey 2.7 with Jackson を使用しています。

public class MyApplication extends ResourceConfig {

    public MyApplication() {
        super(JacksonFeature.class);
        // point to packages containing your resources
        packages(getClass().getPackage().getName());
    }
}

そして、あなたのweb.xml(または私の場合は、ただHashtable)で、あなたのjavax.ws.rs.Applicationをそう指定します

<init-param>
    <param-name>javax.ws.rs.Application</param-name>
    <param-value><MyApplication.class.getName()></param-value>
</init-param>

com.Sun.jersey.config.property.pacakgesまたはcom.Sun.jersey.api.json.POJOMappingFeatureを指定する必要はありません

依存関係を必ず指定してください

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

移動jersey-json pom.xmlのトップへの依存性は、この問題を解決しました。

<dependencies>
  <dependency>
    <groupId>com.Sun.jersey</groupId>
    <artifactId>jersey-json</artifactId>
    <version>1.18.1</version>
  </dependency>

  <!-- other dependencies -->

</dependencies>
1
supercobra