简体   繁体   中英

JAX-RS (Genson + jersey) : Object Not converted to json

I have a sample rest application that runs on tomcat .

When replying - an object of type ActionError is sent to client as a json string.

ActionError will pass to the client an

  1. Array of Strings 2
  2. Array of FieldError s
  3. An arbitrary Object payload (defined as generic type).

In my test I pass as a payload an object of type Employee .

With the above arrangement - everything works fine. And I am getting results like:

{"actionErrors":["everything is ok"],"fieldErrors":null,"payload":{"empName":"Jony","empNo":"E3","position":"Manager"}}

However , if I remove the Array of FieldError ( private ArrayList<FieldError> fieldErrors; ) part, so - that ActionError now only contains:

1. Array of Strings

2. Object payload

then strangely the payload is not serialised properly and I get:

{"actionErrors":["everything is ok"],"payload":"com.mycompany.mavenwebproject.model.Employee@41a8e0d9"}

What cant be causing this ? Any ideas on how could it be fixed?

Thanks.

Below are the class definitions:

ActionError.java

@XmlRootElement(name = "actionError")
@XmlAccessorType(XmlAccessType.FIELD)
public class ActionError<T> {
   private ArrayList<String> actionErrors;
   private ArrayList<FieldError> fieldErrors;
   private T payload;

    /**
     * @return the actionErrors
     */
    public ArrayList<String> getActionErrors() {
        return actionErrors;
    }

    /**
     * @param actionErrors the actionErrors to set
     */
    public void setActionErrors(ArrayList<String> actionErrors) {
        this.actionErrors = actionErrors;
    }

    /**
     * @return the fieldErrors
     */
    public ArrayList<FieldError> getFieldErrors() {
        return fieldErrors;
    }

    /**
     * @param fieldErrors the fieldErrors to set
     */
    public void setFieldErrors(ArrayList<FieldError> fieldErrors) {
        this.fieldErrors = fieldErrors;
    }

    public void addFieldError(String fieldName,String errorMessage){
         if (this.fieldErrors==null)
             this.fieldErrors = new ArrayList<>();
         this.fieldErrors.add(new FieldError(fieldName, errorMessage));
    }

    public void addActionError(String errorMessage){
         if (this.actionErrors==null)
             this.actionErrors = new ArrayList<>();
         this.actionErrors.add(errorMessage);
    }

    public boolean hasErrors(){
      return (fieldErrors!=null && !fieldErrors.isEmpty()) || (actionErrors!=null && !actionErrors.isEmpty());
    }

    /**
     * @return the payload
     */
    public T getPayload() {
        return payload;
    }

    /**
     * @param payload the payload to set
     * @return 
     */
    public ActionError setPayload(T payload) { //Class<T> payloadClass
        this.payload = payload;
        return this;
    }
}

FieldError.java

@XmlRootElement(name = "fieldError")
@XmlAccessorType(XmlAccessType.FIELD)
public class FieldError {
    private String fieldName;
    private String fieldError;

    /**
     * @return the fieldName
     */
    public String getFieldName() {
        return fieldName;
    }

    /**
     * @param fieldName the fieldName to set
     */
    public void setFieldName(String fieldName) {
        this.fieldName = fieldName;
    }

    /**
     * @return the fieldError
     */
    public String getFieldError() {
        return fieldError;
    }

    /**
     * @param fieldError the fieldError to set
     */
    public void setFieldError(String fieldError) {
        this.fieldError = fieldError;
    }

    public FieldError(String fieldName, String fieldError) {
        this.fieldName = fieldName;
        this.fieldError = fieldError;
    }


}

Employee.java

@XmlRootElement(name = "employee")
@XmlAccessorType(XmlAccessType.FIELD)
public class Employee {

    private String empNo;
    private String empName;
    private String position;

    // This default constructor is required if there are other constructors.
    public Employee() {

    }

    public Employee(String empNo, String empName, String position) {
        this.empNo = empNo;
        this.empName = empName;
        this.position = position;
    }

    public String getEmpNo() {
        return empNo;
    }

    public void setEmpNo(String empNo) {
        this.empNo = empNo;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public String getPosition() {
        return position;
    }

    public void setPosition(String position) {
        this.position = position;
    }

}

I managed to run the above both on Glassfish 4.1.1 and Tomcat 8 using following dependencies:

Tomcat 8

<dependency>
    <!-- https://mvnrepository.com/artifact/org.glassfish.jersey.bundles/jaxrs-ri -->
        <groupId>org.glassfish.jersey.bundles</groupId>
        <artifactId>jaxrs-ri</artifactId>
        <version>2.12</version>
        <type>zip</type>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.owlike/genson -->
    <dependency>
        <groupId>com.owlike</groupId>
        <artifactId>genson</artifactId>
        <version>1.4</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.2.7</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.ws.rs/javax.ws.rs-api -->
    <dependency>
        <groupId>javax.ws.rs</groupId>
        <artifactId>javax.ws.rs-api</artifactId>
        <version>2.0.1</version>
    </dependency>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-web-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency>

Glassfish 4.1.1

 <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
  <!-- https://mvnrepository.com/artifact/org.glassfish.jersey.bundles/jaxrs-ri -->      

        <dependency>
            <groupId>org.glassfish.jersey.bundles</groupId>
            <artifactId>jaxrs-ri</artifactId>
            <version>2.12</version>    
            <scope>provided</scope>
            <type>zip</type>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.owlike/genson -->

         <dependency>
            <groupId>com.owlike</groupId>
            <artifactId>genson</artifactId>
            <version>1.4</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.2.7</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.ws.rs/javax.ws.rs-api -->
        <dependency>
            <groupId>javax.ws.rs</groupId>
            <artifactId>javax.ws.rs-api</artifactId>
            <version>2.0.1</version>
        </dependency>
       <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>

Also my web.xml has following entries:

<servlet>
        <servlet-name>jersey-serlvet</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.mycompany.mavenwebproject</param-value>
        </init-param>
        <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>org.glassfish.jersey.jackson.JacksonFeature</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>jersey-serlvet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

Also To run on Glassfish 3.1.2 Jersey 1.x must be used, and there is no need for Genson.

So, the pom.xml dependencies look like this:

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-server</artifactId>
    <version>1.8</version>
</dependency>

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-json</artifactId>
    <version>1.8</version>
</dependency>

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

and the web.xml entry :

<servlet>
        <servlet-name>jersey-serlvet</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>com.mycompany.mavenwebproject</param-value>
        </init-param>
        <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>
    <servlet-mapping>
        <servlet-name>jersey-serlvet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

Edit 1

In order to forgo the use of genson on glassfish 4.1.1 a missing library jackson-module-jaxb-annotations-2.5.4.jar should be added to Glassfish modules directory. Otherwise

java.lang.ClassNotFoundException:
com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector not found by com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider

will be thrown. But if the above jar is added then the pom for the Glassfish could be the following:

Glassfish 4.1.1 (missing library bug fixed)

<dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.3.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
  <!-- https://mvnrepository.com/artifact/org.glassfish.jersey.bundles/jaxrs-ri -->      

        <dependency>
            <groupId>org.glassfish.jersey.bundles</groupId>
            <artifactId>jaxrs-ri</artifactId>
            <version>2.12</version>    
            <scope>provided</scope>
            <type>zip</type>
        </dependency>


        <!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.2.7</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.ws.rs/javax.ws.rs-api -->
        <dependency>
            <groupId>javax.ws.rs</groupId>
            <artifactId>javax.ws.rs-api</artifactId>
            <version>2.0.1</version>
        </dependency>

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

Edit 2.

If one wants to use jackson 2 on Glassfish 3.1.2 with jersey 1 then the following configuration is in order

pom.xml

  <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
  <dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-server</artifactId>
    <version>1.8</version>
</dependency>

<!-- removed to use jackson 2 not 1
<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-json</artifactId>
    <version>1.8</version>
</dependency>
-->

<!-- jackson 2 json provider  -->
<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-json-provider</artifactId>
    <version>2.2.3</version>
</dependency>

<!-- jackson 2 xml provider 
<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-xml-provider</artifactId>
    <version>2.2.3</version>
</dependency>
-->
<dependency>
    <groupId>com.sun.jersey.contribs</groupId>
    <artifactId>jersey-multipart</artifactId>
    <version>1.8</version>
</dependency>
   <dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-web-api</artifactId>
    <version>6.0</version>
    <scope>provided</scope>
    </dependency>
      <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.3.2</version> <!-- unlike jersey 2 on glassfish 4.1.1 here it is not provided! -->
       </dependency>

    </dependencies>

and the web.xml becomes

<servlet>
        <servlet-name>jersey-serlvet</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>
                                     com.mycompany.mavenwebproject
                                    <!--
                                    Jackson 2.x JAX-RS @Providers
                                    -->
                                     com.fasterxml.jackson.jaxrs.json <!--JSON -->
                                     <!-- com.fasterxml.jackson.jaxrs.xml  -->  <!-- XML -->
                        </param-value>
        </init-param>
        <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>
    <servlet-mapping>
        <servlet-name>jersey-serlvet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM