1

I am trying to send a form thru POST to my REST Resource (Java) and I am not able to, as my request gets sent as OPTIONS instead. I Know that the REST Resource is fine since it works perfectly while I test it with Poster Firefox.

jQuery/Ajax call:

function loadTwitter(){
            arrayTweets = new Array();
            var urlTwitter = "http://localhost:8081/streamingvideoservice/services/twitter/retrieveTweets";
            $.ajax({
                    type: "POST",
                    url: urlTwitter,
                    contentType: "application/x-www-form-urlencoded",
                    //accept: "application/json",
                    data: $("form#mapForm").serialize(),
                    dataType: "json",
                    async: false,
                    success: function (resp, status, xhr) {
                       $("#message").html("STATUS: " + xhr.status + " " + xhr.statusText + "\n" + resp);
                       $("#message").hide();
                       $.each(resp, function() {
                            $.each(this, function(i, item) {
                                arrayTweets.push(item);
                            });

                        });

                        displayTweets();
                    },
                    error: function(resp, status, xhr){
                        $("#message").html("ERROR: " + xhr.status + " " + xhr.statusText + "\n" + resp.e);
                        $("#message").show();
                    }
                });
        }

REST Resource:

    @POST
    @Path("/retrieveTweets")
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    @Produces("application/json")
    public List<Tweet> retrieve(@FormParam("lat") Double Latitude, @FormParam("lon") Double Longitude, @FormParam("rad") Integer Radius, @FormParam("from") String From, @FormParam("to") String To) {

        ArrayList<Tweet> lTweets = new ArrayList<Tweet>();
        boolean status = false;

        Twitter twitter = new TwitterFactory().getInstance();

        AccessToken accessToken = new AccessToken(TwitterInterface.ACCESS_TOKEN, TwitterInterface.ACCESS_TOKEN_SECRET);
        twitter.setOAuthConsumer(TwitterInterface.CONSUMER_KEY, TwitterInterface.CONSUMER_SECRET);
        twitter.setOAuthAccessToken(accessToken);

        try {
            Query query = new Query("");
            GeoLocation geo =  new GeoLocation(Latitude, Longitude);
            query.setGeoCode(geo, Radius, Query.KILOMETERS);
            query.setCount(100);
            query.setSince(From);
            query.setUntil(To);
            QueryResult result;
            result = twitter.search(query);
            List<Status> tweets = result.getTweets();
            for (Status tweet : tweets) {
                System.out.println("@" + tweet.getUser().getScreenName() + " - " + tweet.getText() + " - " + tweet.getCreatedAt());
                Tweet t = new Tweet();
                t.setUser(tweet.getUser().getScreenName());
                t.setText(tweet.getText());
                lTweets.add(t);
            }
        }
        catch (TwitterException te) {
            te.printStackTrace();
            System.out.println("Failed to search tweets: " + te.getMessage());
            System.exit(-1);
        }

        return lTweets;

    }

I am using jQuery 1.9.1 and hosting the Resource on Tomcat 6.

Any help is appreciated.

Thanks in advance.

mzereba
  • 2,467
  • 5
  • 26
  • 40
  • Are you doing some CORS(Cross-Origin Resource Sharing) request? – Satpal Mar 07 '14 at 15:07
  • It's all on the same machine...so it is a localhost call (as you can see in my ajax call). Is that what you mean? – mzereba Mar 07 '14 at 15:12
  • @Maged The host (localhost) isn't what determines if it's cross-domain. **Ports** matter too. Is your current web app running on port 8081 too? – Ian Mar 07 '14 at 15:14
  • Correct 8081. To give you a better pic it's a simple HTML page calling Resource running on tomcat. – mzereba Mar 07 '14 at 15:16

2 Answers2

2

You appear to be making a cross origin Ajax request. This requires that the server provides an Access-Control-Allow-Origin header to grant permission to the site hosting the page containing the JS to read the data.

Something about the request (probably the X-Requested-With header that jQuery adds to Ajax requests) is triggering a preflight request which uses an OPTIONS request to ask the server for permission before making the main request.

You will need to configure the server to provide an OPTIONS response with suitable Access Control headers as per the CORS specification (linked above).

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • Thanks for the answer, I read the link you sent me, but how do I make my resource provide "Access-Control-Allow-Origin" is it the Java part, or something on the server? (As I mention I am running the whole thing on my machine; HTML page calling resource running tomcat. – mzereba Mar 07 '14 at 15:15
  • 1
    a .htaccess file can do it. – Kevin B Mar 07 '14 at 15:20
  • 1
    Sorry I am confused here. Do I have to create this file on my application server, or the web app? And what kind of commands have to be in there? – mzereba Mar 07 '14 at 15:27
  • @Maged — The server you are making the request to (i.e. `http://localhost:8081`) has to be able to respond to both the OPTIONS request and the POST request that will be sent in the OPTIONS request gets a good response. The specifics of the headers you should respond to are in the spec I linked to in the answer. See https://developer.mozilla.org/en/docs/HTTP/Access_control_CORS for some alternative documentation. – Quentin Mar 07 '14 at 15:39
  • For some reason i read "Apache Tomcat", maybe he's just using Tomcat? – Kevin B Mar 07 '14 at 15:41
  • @KevinB Yes. HTML file calling web app running on tomcat. Quentin, I do get your point, although what I am not able to understand is where do I have to add this (in the header of the request before sending it, server side in the java code or tomcat)? – mzereba Mar 07 '14 at 15:48
  • @Quentin I have added beforeSend: setHeader. function setHeader(xhr) { xhr.setRequestHeader('Access-Control-Request-Method', 'POST'); xhr.setRequestHeader('Access-Control-Allow-Headers', 'x-requested-with'); } and But it still behaves the same. – mzereba Mar 07 '14 at 15:56
  • @KevinB — Apache makes Apache HTTP and Apache Tomcat. They are different products. – Quentin Mar 07 '14 at 16:04
  • @Maged — They are response headers. You have to add them in the code that runs on the server. The client can't give itself permission to access other origins. – Quentin Mar 07 '14 at 16:05
  • http://stackoverflow.com/questions/9614605/cross-origin-resource-sharing-for-tomcat – Quentin Mar 07 '14 at 16:05
  • @Quentin I've followed this link, I actually installed tomcat 7 as it mentions and added the filter in web.xml file. Now the OPTIONS call is forbidden (error 403). What does that mean? – mzereba Mar 07 '14 at 16:38
-3

Solved it with a GET instead and passing the parameters in the URI.

mzereba
  • 2,467
  • 5
  • 26
  • 40