AJAX JSONP with Jersey / JAX-RS Restful service

后端 未结 1 697
隐瞒了意图╮
隐瞒了意图╮ 2021-01-19 05:16

I\'ve read a lot of questions on stackoverflow but i\'ve not got solution to my problem.

This is my Restful service:

@GET
@Path(\"/GetAllProducts\")
         


        
相关标签:
1条回答
  • 2021-01-19 05:39

    First let me explain some ways we could debug this..

    We could...

    • Change the error function in the AJAX call. The first argument is actually the jqHXR object, not the error message. The arguments actually go jqhxr, status, errorMsg. So if we used the function:

      error: function(jqxhr, status, errorMsg) {
          alert('Failed! ' + errorMsg);
      }
      

      we would see this alert:

      enter image description here

      Doesn't really help in this case if you don't know what it means, but sometimes it's helpful.

    We could...

    • Check the server log

      In this case the server log doesn't show any errors meaning the request was processed successfully and the response was returned.

    We could...

    • Use a browser development tool. For Firefox, you should install Firebug. You can see the request and all the headers and such

    enter image description here

    You can see the request is being made with a callback query parameter. Also pay close attention to the Accept header, which reads application/javascript

    Chrome has the same type of tool, and AFAIK, it is built in, and you can find it under Developer Tools.

    That being said..

    There error comes from the dataType setting in your AJAX request. JSONP is not the same a JSON. JSONP is Javascript code sent back from the server that is meant to be processed by the front end. So jQuery is expecting JSONP format, that's why it set's the headers the application/javascript and that's why the "Syntax Error" message, as JSON format is not the same syntax as JSONP.

    So to fix it, you just simply need to set the dataType as json

    dataType: "json",
    success: function(data) {
        alert("Success: " + JSON.stringify(data));
    },
    

    Now you will see a few things:

    1. The Success message of course:

      enter image description here

    2. The request is no longer being made with the callback query parameter, as that is only for the JSONP protocol.

      enter image description here

    3. The Accept headers now use application/json

      enter image description here


    Just an FYI, contentType sets the Content-Type header. That is only useful when we are sending information, say in a POST request.


    UPDATE

    Just for completeness:

    I'm not sure if you were expecting JSONP outoup, but if you were, one thing you need to know is that JSONP support is not standard in JAX-RS. It dependends on the JAX-RS implementation, how you will need to configure the support.

    First here's how your AJAX request should change to: (or something similar)

    $.ajax({
        url: "http://localhost:8080/Restful/REST/WebService/GetAllProducts",
        type: 'GET',
        jsonp: 'callback',
        dataType: "jsonp",
        success: function(data) {
            alert("Success: " + JSON.stringify(data));
        },
        error: function(jqxhr, status, errorMsg) {
            alert('Failed! ' + errorMsg);
        }
    });
    

    With JSONP, the request will look something like url?callback=someFunctionToCall, where someFunctionToCall is what the server wraps around the JSON, and is the name of the our Javascript function we want to be invoked. So the return response might look something like:

    someFunctionToCall({"name":"MAC", "quantity":"10"})
    

    With jQuery though, we don't need to send the callback query parameter. Its value will be made at random. When I tested, this was the request and response:

    // request
    .../GetAllProducts?callback=jQuery20302583482212586644_1418019088133
    // response
    jQuery20302583482212586644_1418019088133({"name":"MAC", "quantity":"10"})
    

    On return of the response, our success function will be called, passing in the data, as would a normal response. The above AJAX request will alert the exact same message as above.

    Support for Resteasy

    With Reasteasy (3.x.x at least), we should first have the Resteasy Jackson provider

    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jackson2-provider</artifactId>
        <scope>provided</scope>
    </dependency>
    

    All we need to do is add the JSONP interceptor to our deployment

    org.jboss.resteasy.plugins.providers.jackson.JacksonJsonpInterceptor
    

    I haven't gotten the exact science down of which media types need to be added for this support, but I tested with

    @Produces({"text/javascript","application/javascript", "application/json"})
    

    For Jersey 2.x

    Jersey comes with built in support for JSONP, so we don't need any other dependencies, from the default distribution. We just need to add the @JSONP annotation.

    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import org.glassfish.jersey.server.JSONP;
    
    @Path("/WebService")
    public class ProductsResource {
    
        @GET
        @Path("/GetAllProducts")
        @Produces({"application/json", "application/javascript"})
        @JSONP(queryParam = "callback")
        public String getAllProducts() {
            return "{\"name\":\"MAC\", \"quantity\":\"10\"}";
        }
    }
    

    Using the same jQuery code as above, will give the same result. See more at JSON with Padding Support

    0 讨论(0)
提交回复
热议问题