简体   繁体   中英

Using JAXB to parse JSON in Jersey

I'm trying to create a very simple RESTful web service using Jersey. I'm trying to make it so that it consumes and produces a JSON by using JAXB. The problem is that I get an error when I pass a JSON to it.

Below is the resource code. Both status() and echo() are working properly. Please note that on processRequest() I'm currently producing a text response, but that will be changed later to produce a JSON.

package web_service;

import javax.ws.rs.*;
import javax.ws.rs.core.*;

@Path("/")
public class WebService {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String status() {
        return "Web service is up and running.";
    }

    @POST
    @Consumes(MediaType.TEXT_PLAIN)
    @Produces(MediaType.TEXT_PLAIN)
    public String echo(String consumed) {
        return consumed;
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.TEXT_PLAIN)
    public String processRequest(JAXBElement<Request> r) {
        Request request = r.getValue();
        return "Latitude: " + request.latitude +
            "\n:Longitude: " + request.longitude;
    }
}

This is the Request model:

package web_service;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Request {

    public String latitude;
    public String longitude;

    public Request() {}

    public Request(String latitude, String longitude) {
        this.latitude = latitude;
        this.longitude = longitude;
    }

    // Getters and setters for both
}

My web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:web="http://java.sun.com/xml/ns/javaee" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
    id="WebApp_ID" 
    version="2.5">

     <servlet>
         <servlet-name>Jersey REST Service</servlet-name>
         <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

         <init-param>
             <param-name>jersey.config.server.provider.packages</param-name>
             <param-value>web_service</param-value>
         </init-param>

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

    <servlet-mapping>
        <servlet-name>Jersey REST Service</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

Finally, this is an example of the POST that I'm doing (headers set to 'Content-Type: application/json');

{
    "latitude":"25.764084501106787",
    "longitude":"-80.37422332275389"
}

When I run this, Tomcat gives me the following Exception:

WARNING: WebApplicationException cause:
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json, type=class web_service.Request, genericType=class     web_service.Request.

And I get the following response:

415 Unsupported Media Type

Content-Length: 1 kB
Content-Type:   text/html;charset=utf-8
Date:           2013 Nov 4 17:41:20
Server:         Apache-Coyote/1.1

在此处输入图片说明

I'm very new to this and this is not making a lot of sense. Hopefully, one of you will be able to give me a hand. Thanks!

Try this in your endpoint:

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.TEXT_PLAIN)
public String processRequest(Coordinates coordinates) {
    return "Latitude: " + coordinates.getLatitude() +
        "\n:Longitude: " + coordinates.getLongitude();
}

where Coordinates is a simple POJO mirroring the JSON content you are posting.

Then use Jackson, which has JAXB support, by adding all the libraries to your project and adding this configuration:

<init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>org.foobar.rest.services;org.codehaus.jackson.jaxrs</param-value>   
</init-param>

to the "Jersey REST Service" servlet.

JAXB (Java Architecture for XML Binding) avaialable in java for binding xml not for JSON .Here you are trying to convert JavaScript Object Notation with the help of xml binder in this situation and that is not possible. And i am pretty sure that you must be getting the error generated by " BodyWriter class " in the JAX-RS package....

Anyway If you want to produce and consume JSON using your resource you gonna need " moxy " JAR available in your project library for handing this conversion :)

Hope what i am writing here will be helpful for other programmers

this error happends when you are requesting without specified headers. In your service @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.TEXT_PLAIN)

Ensure that your request gets the header "content-type" ? application/json and the header "accept" contains text/html

I think, there is problem with your Request model class. Your model class is not specifying @XmlaccessType, so by default it is being considered as PUBLIC_MEMBER. As your instance variables are also public along with getters and setters, So JAXB is not able to figure out proper bindings.That's why that exception is coming. So there are two fixes to your problem.

1)You can make your instance variables as private. 2)Or you can explicitly specify @XmlaccessType for your model class and likewise provide annotations in it which are non-conflicting.

Add this to your web.xml

<init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>

For more details look at jersey documentation : https://jersey.java.net/documentation/1.18/json.html

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