简体   繁体   中英

Issue with POST JSON to a Jersey REST service

I have a problem with posting JSON to a Jersey REST service - GET is working perfectly but POST seems tricky. I've been working on this problem for awhile now, with no solution so far. Any help is much appreciated!

It seems it cant find the U RL to send the json?Here is what FireBug console shows:

    POST http://localhost:9998/data 400 Bad Request
    Post source: name=Tony
    **Response Headers**
    Connection  close
    Content-Length  0
    Content-Type    text/html; charset=iso-8859-1
    Date    Fri, 20 Apr 2012 10:13:24 GMT
    **Request Headers**
    Accept  application/json, text/javascript, */*; q=0.01
    Accept-Encoding gzip, deflate
    Accept-Language sv-se,sv;q=0.8,en-us;q=0.5,en;q=0.3
    Connection  keep-alive
    Content-Length  9
    Content-Type    application/json; charset=UTF-8
    Host    localhost:9998
    Referer http://localhost:9998/static/page.html
    User-Agent  Mozilla/5.0 (Windows NT 6.1; WOW64; rv:11.0) Gecko/20100101 Firefox/11.0
    X-Requested-With    XMLHttpRequest

I'm doing the POST as follows:

<button id='btn' value="knapp" name="knapp" />
    <script type="text/javascript">
    $('#btn').click(function(){
        $.ajax({
            url: '/data',
            type: 'POST',
            contentType: 'application/json',
            data: {name:"Tony"},
            dataType: 'json'
        });
    })
</script>

Javabean class with @XmlRootElement:

@XmlRootElement
public class StatusBean {
    private String name;

    public StatusBean() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Resource method:

@Path("/data")
public class PostData {
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public StatusBean post(StatusBean sb) {
        System.out.println(sb);
        return sb;
    }
}

The server, set up with Grizzly:

public class Main {
    public static final URI BASE_URI = getBaseURI();

    public static void main(String[] args) throws IOException {
        HttpServer httpServer = startServer();

        Map<String,String> initParams = new HashMap<String, String>();
        initParams.put("com.sun.jersey.config.property.packages", "server");
        SelectorThread selector = GrizzlyWebContainerFactory.create("http://localhost:9998/", initParams );

        System.out.println(String.format("Jersey app started with WADL available at "
                + "%sapplication.wadl\nTry out %shelloworld\nHit enter to stop it...",
                BASE_URI, BASE_URI));

        System.in.read();
        httpServer.stop();
    }

    protected static HttpServer startServer() throws IOException {
        System.out.println("Starting grizzly...");

        ClassNamesResourceConfig rc = new ClassNamesResourceConfig(PostData.class);

//        rc.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, true);

        HttpServer server = GrizzlyServerFactory.createHttpServer(BASE_URI, rc);

        server.getServerConfiguration().addHttpHandler(new StaticHttpHandler(new File(".").getAbsolutePath()), "/static");

        return server;
    }

    private static int getPort(int defaultPort) {
        String port = System.getProperty("jersey.test.port");
        if (null != port) {
            try {
                return Integer.parseInt(port);
            } catch (NumberFormatException e) {
            }
        }
        return defaultPort;
    }

    private static URI getBaseURI() {
        return UriBuilder.fromUri("http://localhost/").port(getPort(9998)).build();
    }
}
  1. Try making your bean serializable.

     @XmlRootElement public class StatusBean implements Serializable { .... } 
  2. Check your POST url. It should be `

    http://localhost:9998/ {projectname}/{restservletmapping}/data

    For example, if my web.xml looks like this and my project name is SampleProject

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

    URL would be : http://localhost:9998/SampleProject/rest/data

    You can use tools for testing REST services like SOAP UI or browser addons like POSTMAN, REST CONSOLE, etc.

  3. If above things are fine and REST service is giving response with testing tools. Then it could be problem of Cross Origin Policy in ajax.

I had the same problem. The issue is that your data is not converted to JSON string automatically. So you just need to call JSON.stringify(...) on your data before posting it:

<button id='btn' value="knapp" name="knapp" />
<script type="text/javascript">
$('#btn').click(function(){
    $.ajax({
        url: '/data',
        type: 'POST',
        contentType: 'application/json',
        data: JSON.stringify({name:"Tony"}),
        dataType: 'json'
    });
})
</script>

This should work.

From your server config I see that you haven't configured JAX-RS with Grizzly. On the base of that example you should somehow pass such property

Map<String,String> initParams = new HashMap<String, String>();
initParams.put( "com.sun.jersey.config.property.packages", "package.with.your.StatusBean.class" );

Another configuration option is to use

ResourceConfig rc = new PackagesResourceConfig("your.package.with.resources");

and start grizzly server:

GrizzlyServerFactory.createHttpServer(BASE_URI, rc);

See details: http://jersey.java.net/nonav/documentation/latest/user-guide.html (Chapter "Deploying the root resource"). Try to run first example they have.

Are you sure that the path you're posting to is complete? You should define another Path annotation on the post method and use that in the URL you're posting to:

@Path("/data")
public class PostData {
    @Path("/postStatus")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public StatusBean post(StatusBean sb) {
        System.out.println(sb);
        return sb;
    }
}

Then use the /data/postStatus path to post your request to:

<button id='btn' value="knapp" name="knapp" />
<script type="text/javascript">
    $('#btn').click(function(){
        $.ajax({
            url: '/data/postStatus',

            type: 'POST',
            contentType: 'application/json',
            data: {name:"Tony"},
            dataType: 'json'
        });
    })
</script>

You have probably forgotten to register the JSON mapper, ie Jackson (or whatever mapper you use). The feature is not enabled automatically, you have to load the class in your ResourceConfig:

org.glassfish.jersey.jackson.JacksonFeature.class

sample

also, see JSON howto

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