1

I have a simple Java application, which reacts to web service request.

When the user presses a button, a message is sent to the Java application.

If the message is "ping", then the application responds with "pong", otherwise - "uknown message".

Code of the Java application:

@Path("/ping-pong")
public class PingPongService {

    @POST
    @Produces("text/plain")
    public String test(@FormParam("message") final String aMessage) {
        System.out.println("message from client: " + aMessage);
        if ("ping".equalsIgnoreCase(aMessage)) {
            System.out.println("ping.equalsIgnoreCase(aMessage)");
            return "pong";
        } else {
            System.out.println("Unknown message");
            return "unknown message " + aMessage;
        }
    }

}

Inside the WAR file, I have following HTML code, which works (when I press one of the buttons, I get the response from the Java application and it is displayed in the message box):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <title>JavaScript Ping-Pong Client</title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <script type="text/javascript">

        //This function send post request to the server using jQuery
        function testWithJQuery(message){
            $.post('http://localhost:8345/rest/ping-pong', { message: message }, function(data) {
                alert(data);
            });
        }

        //This function send post request to the server using a low-level XmlHttpRequest instead of the jQuery
        //(no dependencies on external libraries)
        function test(message){
            var http = new XMLHttpRequest();
            var url = "http://localhost:8345/rest/ping-pong";
            var params = "message=" + message;
            http.open("POST", url, true);
            http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            http.setRequestHeader("Content-length", params.length);
            http.setRequestHeader("Connection", "close");
            http.onreadystatechange = function() {
                if(http.readyState == 4 && http.status == 200) {
                    alert(http.responseText);
                }
            };
            http.send(params);
        }
    </script>
</head>
<body>
    <button onclick="test('ping')">Test</button>
    <button onclick="testWithJQuery('ping')">Test using jQuery</button>
</body>
</html>

I want to do exactly the same thing (user presses a button, a message is sent to the Java application and its response displayed in an alert message window) in a Django application.

Django generates following HTML code:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title></title>

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
    //This function send post request to the server using jQuery
    function testWithJQuery(message){
        $.post('http://localhost:8345/rest/ping-pong', { message: message }, function(data) {
            alert(data);
        });
    }

    //This function send post request to the server using a low-level XmlHttpRequest instead of the jQuery
    //(no dependencies on external libraries)
    function test(message){
        var http = new XMLHttpRequest();
        var url = "http://localhost:8345/rest/ping-pong";
        var params = "message=" + message;
        http.open("POST", url, true);
        http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        http.setRequestHeader("Content-length", params.length);
        http.setRequestHeader("Connection", "close");
        http.onreadystatechange = function() {
            if(http.readyState == 4 && http.status == 200) {
                alert(http.responseText);
            }
        };
        http.send(params);
    }
</script>


</head>
<body>
<button onclick="test('ping')">Test</button>
</body>
</html>

When I press the "Test" button in Django-generated code, the Java application receives the message (I see this in the console output), but the response of the Java application is not displayed in Django web site, even though the HTML code is identical to the one in the WAR file.

How can I fix this, i. e. make sure that the response of the Java application is displayed in Django?

UPD: Here's the detailed error description in the "Network" pane of Chrome:

enter image description here

Glory to Russia
  • 17,289
  • 56
  • 182
  • 325
  • 1
    Have you tried ``? – Paulo Scardine Jul 26 '12 at 00:05
  • If the output HTML is identical (which is isn't), then the language used to generate it is completely irrelevant. – Hamish Jul 26 '12 at 01:45
  • @PauloScardine: Yes, I tried that and the result is the same. – Glory to Russia Jul 26 '12 at 03:37
  • 1
    Debug this code with your browser. Firefox, Safari and Chrome all have developer tools which can debug javascript. Take a look at the "error console" in your browser. Maybe there is a clue to what's wrong. But basically this should work. To my knowledge it is completely irrelevant if the html is rendered by Django, Java or whatever. Your code should work. – Jens Jul 26 '12 at 10:45

1 Answers1

1

This is not an straight answer but rather some tips to help you diagnose the problem; I'm posting here because it is too big for a comment.

  1. open the Chrome debugger (shif+ctrl+i) or Firefox Firebug and make the Network tab active.
  2. inspect the post made by both versions and compare headers and body

If there is distinct behavior, there should be some differences between both posts.

[update]

I found the error - see the screenshot in the question. The error is "XMLHttpRequest cannot load localhost:8345/rest/ping-pong. Origin localhost:8000 is not allowed by Access-Control-Allow-Origin.".

The error is due to security constraints in the browser (same origin policy). There are some workarrounds (source: wikipedia):

To enable developers to, in a controlled manner, circumvent the same origin policy, a number of "hacks" such as using the fragment identifier or the window.name property have been used to pass data between documents residing in different domains. With the HTML5 standard, a method was formalized for this: the postMessage interface, which is only available on recent browsers. JSONP and cross-origin resource sharing can also be used to enable ajax-like calls to other domains.2 easyXDM can also be used to easily work around the limitation set in place by the same origin policy. It is a lightweight, easy-to-use and self-contained Javascript library that makes it easy for developers to communicate and expose javascript APIs across domain boundaries.

I've used the subdomain hack with success, see this answer:

Community
  • 1
  • 1
Paulo Scardine
  • 73,447
  • 11
  • 124
  • 153
  • I found the error - see the screenshot in the question. The error is "XMLHttpRequest cannot load http://localhost:8345/rest/ping-pong. Origin http://localhost:8000 is not allowed by Access-Control-Allow-Origin.". – Glory to Russia Jul 26 '12 at 17:12
  • @DmitriPisarenko: answer updated with pointers to the cause and solutions. – Paulo Scardine Jul 27 '12 at 01:45
  • Thanks. At http://www.flickr.com/photos/iluvrhinestones/5889370258/ there is a decision tree for choosing the technology for such task. One of the options are web sockets. Are they suitable for my needs? Note that my application will never exchange sensitive data with the server. – Glory to Russia Jul 27 '12 at 12:32
  • Hard to tell unless you update your question with the answers to that decison chart - that said... If you have control over the DNS and both applications, the easier path is the subdomain hack. If you don't have to support old browsers, web sockets are a good tool to add to your toolbox (just use a library, no need to reinvent the wheel). – Paulo Scardine Jul 27 '12 at 15:36