Web services in Django - java

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:

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.
open the Chrome debugger (shif+ctrl+i) or Firefox Firebug and make the Network tab active.
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:
Ways to circumvent the same-origin policy

Related

How to access API controller from Spring in HTML

This is my controller:
#GetMapping("/getRandomWildSwimming")
public List<WildSwimming> getRandomWildSwimming() {
return wildSwimmingService.getRandomWildSwimming();
}
How I can access it with HTML? I'm confused, I saw some tutorials where I set return index.html for example, but I'm returning here actually service that show me collection data from Mongo in JSON when I send request for example: http://localhost:8080/wildswimming/getRandomWildSwimming page show me one collection from mongo in JSON format, how I can show that via html and stylize it a bit?
If you want to use this approach, you need a client. For example, you can use JS or PHP for it.
Then you need to create HTML pages, add scripts (using JS or PHP) to send requests, get responses and show it to user.
This looks like: user opens page -> client sends request to your spring controller -> spring controller returns response -> client gets and shows it to user.
OR
You can use Spring MVC if you do not how to launch client server.
You will need to add a dependency to your project so that spring boot knows how to convert an object into json. If you're using maven, add com.fasterxml.jackson.core:jackson-databind to your pom file.
Then, add the #ResponseBody annotation to the getRandomWildSwimming method so that it ends up looking like this...
#GetMapping("/getRandomWildSwimming")
public #ResponseBody List<WildSwimming> getRandomWildSwimming() {
return wildSwimmingService.getRandomWildSwimming();
}
This will make the controller respond with json when it is called in a web browser.
Assuming that it returns JSON that looks like this...
[{"rating":89},{"rating":24},{"rating":68}]
You can using the $.get function (from the jquery library), to make a call to the /getRandomWildSwimming api method, which will fetch the JSON and automatically convert it into a javascript array of objects...
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script src="resources/jquery-3.6.0.min.js"></script>
</head>
<body>
<h1>Wild Swimming Records</h1>
<ul id="canvas">
</ul>
<script type="text/javascript">
$(document).ready(function(){
$.get("./getRandomWildSwimming", function(data) {
console.log(data[0].rating);
console.log("JSON: " + JSON.stringify(data));
$.each(data, function(index, value) {
$("#canvas").append("<li>" + value.rating + "</li>");
});
});
});
</script>
</body>
</html>
This should result in a page that looks something like this...
Wild Swimming Records
- 89
- 24
- 68
The first console.log line will take the rating property of the first object in the data array and print it to the browser console. The second console.log line will convert the entire array back into a json string and print it to the browser console.

How to call SAML (http-post binding) based REST APIs using Angular?

I have OData REST APIs protected with SAML 2.0(POST binding) and I have Angular 2+ client application. How can I call these REST APIs using Angular application?
When I use Angular HTTP client
import {Http, RequestOptions, Request, RequestMethod} from '#angular/http';
I'm getting form with continue button to Note:Since your browser does not support JavaScript, you must press the Continue button once to proceed.
If I hit same REST API URL directly in browser, then browser redirects to IDP and then, after successful authentication, IdP redirects back it to REST API.
The same behavior is observed on Postman, but they are fixing it by enabling JS script preview.
Here is Angular code which i tried:
this.POST('https://<RESTAppfqdn>/odata', {"ID": "2"}).subscribe(data => {
console.log(data)
})
}
POST(url, data) {
const headers = Object.assign({
'Content-Type': 'application/x-www-form-urlencoded',
Accept: 'application/json;vnd.ptc.ilm.webui2.0=true;text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
});
var requestoptions = new RequestOptions({
method: RequestMethod.Post,
url: url,
headers: headers,
body: data
})
return this.http.request(new Request(requestoptions))
.pipe(map(res => res.json()));
}
Here is response I can see in browser's network tab:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
</head>
<body onload="document.forms[0].submit()">
<noscript>
<p>
<strong>Note:</strong> Since your browser does not support JavaScript,
you must press the Continue button once to proceed.
</p>
</noscript>
<form action="https://<Idpfqn>:9031/idp/SSO.saml2" method="post">
<div>
<input type="hidden" name="SAMLRequest" value="PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgQXNzZXJ0aW9uQ29uc3VtZXJTZXJ2aWNlVVJMPSJodHRwczovL0tJU0pBREhBVjJMMS9zYW1sL1NTTyIgRGVzdGluYXRpb249Imh0dHBzOi8va2lzamFkaGF2MmwxLnB0Y25ldC5wdGMuY29tOjkwMzEvaWRwL1NTTy5zYW1sMiIgRm9yY2VBdXRobj0iZmFsc2UiIElEPSJhM2UzOTMyZjAzNTNmNWI3NTFoYmc4ZWpmY2lkNTViIiBJc1Bhc3NpdmU9ImZhbHNlIiBJc3N1ZUluc3RhbnQ9IjIwMTktMDQtMjVUMDY6MTc6MjUuOTQzWiIgUHJvdG9jb2xCaW5kaW5nPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YmluZGluZ3M6SFRUUC1QT1NUIiBWZXJzaW9uPSIyLjAiPjxzYW1sMjpJc3N1ZXIgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPmh0dHBzOi8vS0lTSkFESEFWMkwxL3NhbWwvbWV0YWRhdGE8L3NhbWwyOklzc3Vlcj48ZHM6U2lnbmF0dXJlIHhtbG5zOmRzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj48ZHM6U2lnbmVkSW5mbz48ZHM6Q2Fub25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjcnNhLXNoYTEiLz48ZHM6UmVmZXJlbmNlIFVSST0iI2EzZTM5MzJmMDM1M2Y1Yjc1MWhiZzhlamZjaWQ1NWIiPjxkczpUcmFuc2Zvcm1zPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVyZSIvPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48L2RzOlRyYW5zZm9ybXM+PGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNzaGExIi8+PGRzOkRpZ2VzdFZhbHVlPlNDc3dxRG5FTThNWEJvSnZkRGhrdEE3dGF5VT08L2RzOkRpZ2VzdFZhbHVlPjwvZHM6UmVmZXJlbmNlPjwvZHM6U2lnbmVkSW5mbz48ZHM6U2lnbmF0dXJlVmFsdWU+YkxTd3pjRFhYUmNQV1VYa2hHbXB4RXZEQ3JlRWFpc2tka2drTzl5eGpkdGFlalhnSEVBNHRQNWhuL2FyRVh4T0NxWHlmWnFBRXFZZFduTE5vODJyNXZoQ1F2SGhWdEJHTUY0T1FSbXlDT2FwUHRPamdINWtpRW1uaVVHNHduaEpERCsxRWR3L2x2ZFlJd0svSEhCSE8zV2p4eTZ3aW9hbUhMRGczYWNNM0QzdHNMMFR0VlM0RVZETncxeFBmeTdUWTd6WVZqYWUrcmZqRm9IZUlEQlZYdFNnS2xSL2RHbW1DMXBaTDFydWVsZHkzSEJRV3dYVWx5S1NRa09oNU9VWnBCeWttMHBERDhmNnA4UVV3Uy8zTEtxd3hvc1NiWlVIMlJoUHI0RFIwTDMwQjNzSmlka1JKMGI0eUdHNlFzZnlGY3lVZERxdHVDS3FhVkpMR1htSXNnPT08L2RzOlNpZ25hdHVyZVZhbHVlPjxkczpLZXlJbmZvPjxkczpYNTA5RGF0YT48ZHM6WDUwOUNlcnRpZmljYXRlPk1JSURYVENDQWtXZ0F3SUJBZ0lFVXZvcnFEQU5CZ2txaGtpRzl3MEJBUXNGQURCZk1Rc3dDUVlEVlFRR0V3SnBiakVMTUFrR0ExVUUNCkNCTUNiV2d4RFRBTEJnTlZCQWNUQkhCMWJtVXhEREFLQmdOVkJBb1RBM0IwWXpFUE1BMEdBMVVFQ3hNR2NIUmpibVYwTVJVd0V3WUQNClZRUURFd3hMU1ZOS1FVUklRVll5VERFd0hoY05NVGt3TkRJME1UZzBOekV3V2hjTk1qQXdOREU0TVRnME56RXdXakJmTVFzd0NRWUQNClZRUUdFd0pwYmpFTE1Ba0dBMVVFQ0JNQ2JXZ3hEVEFMQmdOVkJBY1RCSEIxYm1VeEREQUtCZ05WQkFvVEEzQjBZekVQTUEwR0ExVUUNCkN4TUdjSFJqYm1WME1SVXdFd1lEVlFRREV3eExTVk5LUVVSSVFWWXlUREV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXcNCmdnRUtBb0lCQVFDblM2MmdHQ2llcHZJMXFVdCt4a1d1bjJRenlUWUlLay9DQ0w3WkxVUlkyVmluS0w4UUFGb0xnM0s2bGJCaTVPeEENCjI2em9ZY3cyVHJ5a1FmL2ZuSG04eXpEVWJWSzlmZ0NXVXBzT2tOZnUyMHVZUzc2cTBna0tmbGFFR2Q4UzFFUStVUGMvT0pkem5NTXMNCkpzckZldXZYMVpqZFMzWG9mZlBDZXcvOGdIQzR2dTU1V0tGSDhvODUxQWdRdXRrNzlUYUpYUm5zN0VpUVhvMkVBVnNTUWIrZXpoWGYNCnJuYXNMN1BhUGFWT0JQV1RBTi83VERSZEs4R1RiUHRrWG8wMnIxZnNoZk5rRW05VDhROTBFNmtmU1l6emt3MXByRktwY1RncTZsbmUNClFFMk4zNEpCVTdjUHlYVW8yRHVNNkxVVXZndWFLK2xDK05TamZENWliMFNTcDdtdkFnTUJBQUdqSVRBZk1CMEdBMVVkRGdRV0JCU28NCmxUS3d3dkoxdzBsZjkwZURPWTluUlY4bjJqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFYRzA4ZWphdjQxYWJtQS9jZkNZUFQrWVINClhQSnZzQ1F1YTJRempRSy9IMDdNclJsOTVCSkkzeUJEQ1pJaW9ndU5YbS9sbHVxYzV1VWJtekdBenBFM3MybnZtbjQ0bjBhUVYyd28NCkxja2NiWUZJUkNFRFhOZXFZUEUrZFVGdVgwSEJ5dlFqNU9FSU9wZTlYTzUrZ1lFUUlXZWxTZXFibUF0UmRuWi84ZWlFY3h6bEFaTlINCkRITDlxdjloK2doNFpPM3BkRVNLdWM3Z0NKODFXVGNueUN1QS9ZS1ZMR2lnM0plbEJJYkhwZTVXcXBaR3dPUG9WYk82cVViTzlHQjUNCmxVQkxYRlF3cmVSazlTV3JVQkV5Wi8yQ3ovY1UvVjRnSms4cGdTWTFPVHNOUmpGanZKVjd1TnBQeEsxam1nRkRsakV5aXpHay96WGENClJDNjE1VVhIbExpb093PT08L2RzOlg1MDlDZXJ0aWZpY2F0ZT48L2RzOlg1MDlEYXRhPjwvZHM6S2V5SW5mbz48L2RzOlNpZ25hdHVyZT48L3NhbWwycDpBdXRoblJlcXVlc3Q+"/>
</div>
<noscript>
<div>
<input type="submit" value="Continue"/>
</div>
</noscript>
</form>
</body>
</html>```
As Angular http client reside in browser, browser should take care of handling this post form submission and redirection work but that is not happening. Is there any way by which i can tell browser to handle such responses?
As there is form in response received from server, I have submit that form.
Hence, I have created a div (ex. auth) in index.html and when the response contains the form then submit that. Here is that code.
if (res['error']['text']) {
let authDiv = document.getElementById('auth')
authDiv.innerHTML = res['error']['text']
var f1 = authDiv.children[1]
f1.submit()
return new HttpResponseFailAction([res['error']['text']])
}
But then we will face another issues with that:
Ex. The auth challenge received from IdP has to be displayed.
Basically, we need to act like browser and any coming requests we need to handle.
Hence, I decided to discarded this approach and added SAML SSO support to client application itself.

SpingMVC + Angularjs+ POST with jsp

new to angularjs. I am sure i am missing something.
I am unable to render the response send by server on jsp page if i hit server with angularjs's $http directive.
angularcode
// Read button Handler
$scope.readAll=function(){
readTable($scope.clnfamilyArray);
//send data to server
testAddItem=function(){
$http({
'url' : 'http://localhost:9090/QuantumM/orbital/sendstatement/',
'method' : 'POST',
'headers': {'Content-Type' : 'application/json'},
'data' : $scope.clnfamilyArray
}).success(function(data){
console.log(data);
})
}//end of function
testAddItem();
}////end of readAll
spring code
#RequestMapping(value = "/sendstatement/", method = RequestMethod.POST)
public ModelAndView welcome(#RequestBody String map) {
ModelAndView model = new ModelAndView();
// BL
model.addObject("name",hTable.toHtml());
model.setViewName("test");
return model;
}
test.jsp
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<h1>Gradle - Spring MVC Hello World</h1>
<h2>Hello ${name}</h2>
</body>
</html>
Instead of rendering test.jsp. I am landing on the same page. But on console I can see the expected output..
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<h1>Gradle - Spring MVC Hello World</h1>
<h2>Hello <table border=1><tr><td colspan=2>s</td></tr><tr><td colspan=1>f</td><td colspan=1>d</td></tr></table></h2>
</body>
</html>
Is there anything which I am missing ???
I wanted to landed on test.jsp not on my current calling page...
You are missing something, as you guessed. The purpose of the $http call is to fetch the results of an HTTP call and provide it to your AngularJS application's model. It is not meant to redirect you to a new page on another server.
The reason you see the page output in the console is due to the .success() portion of the http call:
$http({
'url' : 'http://localhost:9090/QuantumM/orbital/sendstatement/',
'method' : 'POST',
'headers': {'Content-Type' : 'application/json'},
'data' : $scope.clnfamilyArray
}).success(function(data){ // The data is passed here when received
console.log(data);
})
It's an async call handled by a promise. So your app makes the http call, and then goes on its merry way. When the data from that http call is available, it is passed to your .success() call and then you log it to the console. Here's a Plunk demo I did showing how promises work in serial and parallel so you can see some of their benefit.
This is not the Angular way. What you should be doing for a single-page-app in AngularJS is fetch the DATA from the server, not a rendered page, and then display it to the user with AngularJS views.
Instead of having your SpringMVC app render the view, have it pass the model back as JSON data. That way, you will be able to easily show it to the user in your AngularJS view.
My guess is that if you took your example and had it return JSON, it would return something like:
{
"name": "Bob"
}
Then you would change the .success() call to do something like this:
.success(function(data) {
$scope.name = data.name;
})
And in your view, you would show it with:
<p>Hi {{name}}</p>
Hope this helps.

Displaying waiting page before processing the request in Spring

actually I am developing a application using Spring MVC, in one case I have to make the user to wait for the results by displaying a page..and once the back end processes the request..the results will be loaded. Can anyone please tell me how can I achieve that?
I'd say this is more of a javascript solution than necessarily a Spring one.
Lets say you're waiting on a request from the back end process, you could use the solution here to wait for a response while your back end produces the data you require.
The code below would show the code within the loaderImage id (say it's a div in html), then hide it when the success is loaded. The ajax request would just be whatever POST or GET you use to get to your back end controller.
$('#loaderImage').show();
$.ajax({
// Other ajax parameters
success: function () {
// hiding the image here
$('#loaderImage').hide();
}
});
You can use
window.onload();
<!doctype html>
<html>
<head>
<title>onload test</title>
<script>
function load() {
alert("load event detected!");
}
window.onload = load;
</script>
</head>
<body>
<p>The load event fires when the document has finished loading!</p>
</body>
</html>
SO there you can remove your loading div or html.
https://developer.mozilla.org/en-US/docs/DOM/window.onload

Spring MVC + JQuery + Ajax Issue

I'm trying to make an Ajax call to my Spring MVC app using a Jquery Ajax. The app controllers are working fine but I can't get this Ajax test controller to work. The alert is triggered but the call to the controller is never made. I've also tried using load, get, post. None of them call the server. Which makes me think I'm doing something obviously wrong. If I put the URL directly on the browser address bar, the controller is called.
If someone can guide me in the right direction or tell me what I'm doing wrong, I'd be grateful.
JavaScript
<html>
<head>
<script type="text/javascript" src="jquery-1.8.1.min.js"> </script>
<script type="text/javascript">
function doAjax() {
alert("did it even get here?");
$.ajax({
url : "simpleRequestTest.do",
method: "GET",
success : function(response) {
$('#show').html(response);
}
});
}
</script>
</head>
<body>
<h1>Simple Test </h1>
Simple Test
<br />
<div id="show">...</div>
</body>
</html>
Controller
#RequestMapping("/simpleRequestTest")
public #ResponseBody String performSimple() {
return "Very Simple Test";
}
Can you check whether you use correct path for include the jquery-1.8.1.min.js.
I checked the code it's working file for me.
I think you are missing dataType in ajax call
try this
function doAjax() {
alert("did it even get here?");
$.ajax({
url : "simpleRequestTest.do",
method: "GET",
success : function(response) {
$('#show').html(response);
},
dataType: 'text'
});
}
Just change url : "simpleRequestTest.do", to url : "simpleRequestTest", and method: "GET", to type: "GET",
I think the method is removed in the jquery version 1.5 and latest

Categories