3

I've delved into StackOverflow for days and went through these links 1 and 2 and 3 but all to no avail.

I am a newbie in java web applications. I am using Tomcat 9.0.4 and Jersey 1.18 in my project. I want to pass 4 parameters as 4 points to a post web service written in JAX-RS and get back the area and perimeter in response. This is my server-side web service:

    @path("/geo")
    public class geonodes{
      static double area(double x1,double y1,double x2,double y2){
      //do area calculation
      }
      static double perimeter(double x1,double y1,double x2,double y2){
      //do perimeter calculation
      }
      @POST
      @Produces(MediaType.APPLICATION_JSON)
      public Response calculate(@QuerParam("x1") Double x1,@QuerParam("y1") Double y1,@QuerParam("x2") Double x2,@QuerParam("y2") Double y2){
        JSONObject obj = new JSONObject();
        obj.put("area",area(x1,y1,x2,y2));
        obj.put("perimeter",perimeter(x1,y1,x2,y2));
        result = JSONObject.toJSONString(obj);
        return Response.status(201).entity(result).build();
    }

and this is my ajax client-side call:

$.ajax({
    url:'http://localhost:8080/api/geo',
    type:'POST',
    dataType:'json',
    contentType:'application/json',
    data:JSON.stringify({x1:22.1,y1:44.19,x2:55.33,y2:49.72}),
    success:function(data){console.log(data);},
    error:function(errMsg){console.log(errMsg);},
});

I use a non-maven project including these jar files:

Lib

And this is my web.xml

    <servlet>
        <servlet-name>Geo Nodes API</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>example,com.fasterxml.jackson.jaxrs.json</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>Geo Nodes API</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>
    <filter>
        <filter-name>CorsFilter</filter-name>
        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CorsFilter</filter-name>
        <url-pattern>/api/*</url-pattern>
    </filter-mapping>

The response was always null and after a long search and google, I found the problem in parameters so in response I returned them. when I call the address by the postman the result returns correctly as below: postman_200 But invoking by ajax or another system, the parameters are always null. ajax

Whenever I use something except @QueryParam i.e the class with getter and setter like below code the postman gets the 415 error either. The Coordinats.java class:

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Coordinates {
    private Double x1;
    private Double y1;
    private Double x2;
    private Double y2;

    public Double getX1() {
        return x1;
    }
    public void setX1(Double x1) {
        this.x1 = x1;
    }
    public Double getY1() {
        return y1;
    }
    public void setY1(Double y1) {
        this.y1 = y1;
    }
    public Double getX2() {
        return x2;
    }
    public void setX2(Double x2) {
        this.x2 = x2;
    }
    public Double getY2() {
        return y2;
    }
    public void setY2(Double y2) {
        this.y2 = y2;
    }

}

The server-side code snippet:

import model.Coordinates;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;

@Path("geo")
public class Geo {

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Coordinates request(Coordinates coordinates){
        Double x1 = coordinates.getX1();
        Double y1 = coordinates.getY1();
        Double x2 = coordinates.getX2();
        Double y2 = coordinates.getY2();
        return coordinates;
    }
}

postman_415 This is the stack trace:

04-Dec-2020 05:53:14.771 SEVERE [http-nio-8080-exec-7] com.sun.jersey.spi.container.ContainerRequest.getEntity A message body reader for Java class model.Coordinates, and Java type class model.Coordinates, and MIME media type application/json was not found.
The registered message body readers compatible with the MIME media type are:
application/json ->
  com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$App
  com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$App
  com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$App
*/* ->
  com.sun.jersey.core.impl.provider.entity.FormProvider
  com.sun.jersey.core.impl.provider.entity.StringProvider
  com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
  com.sun.jersey.core.impl.provider.entity.FileProvider
  com.sun.jersey.core.impl.provider.entity.InputStreamProvider
  com.sun.jersey.core.impl.provider.entity.DataSourceProvider
  com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
  com.sun.jersey.core.impl.provider.entity.ReaderProvider
  com.sun.jersey.core.impl.provider.entity.DocumentProvider
  com.sun.jersey.core.impl.provider.entity.SourceProvider$StreamSourceReader
  com.sun.jersey.core.impl.provider.entity.SourceProvider$SAXSourceReader
  com.sun.jersey.core.impl.provider.entity.SourceProvider$DOMSourceReader
  com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$General
  com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General
  com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General
  com.sun.jersey.core.impl.provider.entity.XMLRootObjectProvider$General
  com.sun.jersey.core.impl.provider.entity.EntityHolderReader
  com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$General
  com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$General

I added every jar file that is needed and now I'm confusing what's wrong!? When I pass an object I get a 415-error and when I pass @QueryParam the parameters are accessible by the postman call not accessible by ajax call though!!!

1 Answers1

2

If you want to send JSON, then what you have here is correct

@Path("geo")
public class Geo {

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Coordinates request(Coordinates coordinates){
        Double x1 = coordinates.getX1();
        Double y1 = coordinates.getY1();
        Double x2 = coordinates.getX2();
        Double y2 = coordinates.getY2();
        return coordinates;
    }
}

You have all the Jackson jars. You should remove the POJOMappingFeature in your web.xml and remove the jersey-json jar as this might cause some conflict.

Then add the following in the web.xml

<init-param>
    <param-name>com.sun.jersey.config.property.packages</param-name>
    <param-value>
        example,
        com.fasterxml.jackson.jaxrs.json
    </param-value>
</init-param>

This will tell Jersey to scan the Jackson package for the JSON provider.

Now in your Postman call, do not use the "params" as that will not create JSON. you should use the "body" tab and then manually type in the JSON you want to send

{
  "x1": 1.1,
  "y1": 2.2,
  "x2": 3.3,
  "y2": 4.4
}

Then set the Content-Type header to application/json

After doing all this, it should work. As an aside, I highly suggest you learn to use a dependency manager, either Maven or Gradle. Trying to add jars, you often will miss adding the jars that that jar depends on, which will cause that jar not to work.

Paul Samsotha
  • 188,774
  • 31
  • 430
  • 651