I have written java web application (front-end) using JSF.
I use Jersey RESTful Web Services framework
version 1.8
to send data to the back-end.
The back-end is jax-rs
RESTful Web Service using spring boot
.
In front-end I have GET
methods (Using Jersey-client
), these methods work without any problem.
When I post JSON data using the Postman
software it is also working without any problem, but when I sent my Customer
object using front-end application (Using Jersey client) it gives me this error:
WARN 2156 --- [io-8089-exec-53] .w.s.m.s.DefaultHandlerExceptionResolver :Failed
to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException:
JSON parse error: Cannot construct instance of `com.example.demo.model.Customer`
(although at least one Creator exists): no String-argument constructor/factory
method to deserialize from String value
('{"id":0,"name":"abc","city":"def","contactNum":334455}'); nested exception is
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct
instance of `com.example.demo.model.Customer` (although at least one Creator exists):
no String-argument constructor/factory method to deserialize from String value
('{"id":0,"name":"abc","city":"def","contactNum":334455}')
Here is my front-end method for send data.
public static void saveCustomer(Customer customer) throws IOException {
Gson gson = new Gson();
String custJson = gson.toJson(customer);
System.out.println(custJson);
Client create = Client.create();
WebResource webResorce = create.resource("http://localhost:8089/springHibernate/addCus");
ClientResponse response = webResorce.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(ClientResponse.class, custJson);
if (response.getStatus() != 201) {
response.close();
throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
}
System.out.println("Output from Server .... \n");
String output = response.getEntity(String.class);
System.out.println(output);
response.close();
}
Here is the back-end service
@RequestMapping(value = "/addCus", method = RequestMethod.POST,produces = MediaType.APPLICATION_JSON_VALUE)
public Customer process( @RequestBody Customer cus) throws Exception {
Customer saveCus = customerSrvice.saveCus(cus);
return saveCus;
}
EDIT The Customer
class
package com.example.demo.model;
@Entity
@Table(name="customer")
public class Customer implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO )
private int id;
@Column(name = "name")
private String name;
@Column(name = "city")
private String city;
@Column(name = "contactNum")
private int contactNum;
public Customer() { }
public Customer(String name, String city, int contactNum) { /**/ }
public Customer(int id, String name, String city, int contactNum) { /**/ }
}
The front-end pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.keylesson.jsf22</groupId>
<artifactId>PrimeFaces-Hello-World-Example</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<name>PrimeFaces-Hello-World-Example</name>
<url>http://maven.apache.org</url>
<dependencies>
<!-- JSF2.2 dependency -->
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.2.8</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.2.8</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2.1-b03</version>
</dependency>
<!-- PrimeFaces dependency -->
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>6.2</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.9</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.8</version>
</dependency>
<!-- this dependancy help to map json to java object dependency -->
<dependency>
<groupId>com.owlike</groupId>
<artifactId>genson</artifactId>
<version>0.99</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
<type>jar</type>
</dependency>
</dependencies>
The Back-end pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>springHibernate</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>springHibernate</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I can get your example to work until I add this library
<dependency>
<groupId>com.owlike</groupId>
<artifactId>genson</artifactId>
<version>0.99</version>
</dependency>
Then I get the same error as you:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of
com.example.demo.model.Customer
(although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"id":0,"name":"abc","city":"def","contactNum":334455}')
So I assume the error is created by this library. I tried 1.4
too, which is the last version, and it breaks too.
Solution that worked for me on minimal code where I reproduced your issue. You can try it out.
I added a String-argument
constructor to Customer
(this is what the error complains about):
public Customer(String json) throws IOException {
Customer c = new ObjectMapper().readValue(json, Customer.class);
this.id = c.id;
this.name = c.name;
this.city = c.city;
this.contactNum = c.contactNum;
}
This is called when the Spring
back-end tries to convert the JSON String to a Customer
. It seems to be necessary if you want to use genson
.
I don't know if this is the proper solution or simply a workaround, but it works.