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
Array
of Strings
2 Array
of FieldError
s 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.