React REST request to Java backend failing - java

I have a simple React form. I am trying to send the data from this form using Fetch API to my Java backend. Here is my React Form file:
import React, {Component} from 'react';
class Form extends Component {
constructor(props){
super(props);
this.state={value:""};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event){
event.preventDefault();
this.setState({value:event.target.value});
}
handleSubmit(event){
event.preventDefault();
const data = new FormData(event.target);
fetch('http://localhost:8080/add/person', {
method: 'POST',
body: data
});
}
render(){
return(
<form onSubmit={this.handleSubmit}>
<label>Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit"/>
</form>
);
}
}
For some reason, the data variable always has an empty JSON when I am in debug mode. In my Java backend, when I receive the request, I am seeing blank form data.
Any ideas as to why I am not able to send data across to my Java backend?
EDIT: I would also like to point out that my frontend is hosted on localhost:3000, while my Java backend server is on localhost:8080

why not just submit your data using the value stored in state?
handleSubmit(event){
event.preventDefault();
const data = this.state.value; //change here
fetch('http://localhost:8080/add/person', {
method: 'POST',
body: data
});
}
UPDATE: in your package.json add "proxy": "http://localhost:8080" if that doesn't work you will have to open it up using something like this but for what ever framework you're using on your backend.
https://www.npmjs.com/package/cors#enabling-cors-pre-flight
http://www.baeldung.com/spring-cors
as #Tadas Antanavicius said your input is also missing a name value. here is a nice and short medium article on the react portion of what you are trying to do with your code. you can even remove your onChange from your input field.
https://medium.com/#everdimension/how-to-handle-forms-with-just-react-ac066c48bd4f

Your problem is unrelated to your backend - the fetch code looks correct.
FormData is not being constructed as you would expect. You can try this out by opening Chrome Devtools' Network tab and watch the request as it goes by: empty request payload.
The problem is that the FormData constructor's argument relies on each input in the form having a name attribute, which you're missing. If you add it, (name="name") your front end should behave as expected:
<input type="text" name="name" value={this.state.value} onChange={this.handleChange} />
EDIT: As per your above conversation, seems like you also have a server side CORS issue. My answer fixes your original question, but yes you'll need to resolve the CORS one as well, the easiest way probably being to refer to the docs of whatever Java framework you're using. It's a very common problem and should be in FAQ.

Related

Migrating app to AngularJS?

i have existing web application where most of the time pages are submitted traditional way(like document.form.submit or )
I am planning to migrate to angularJS which i am learning. I am not sure how we can submit form in traditional way (without ajax) with angularJS ?
I know it won't be true Single Page App(SPA), but for starting i would like to go this way.
Approach for migrating traditional app to SPA :-
In future , i would like to go for SPA in which i will submitting the form thru ajax way using AngularJS. I have vague understanding
how will i approach this but would like to get experts advice on this.
My Understanding:-
Say i land to welcome page with a link for customer creation. I will make the ajax call from WelcomeController(angularJS Controller) to my servlet/spring controller
which will return html response containing js file. HTML response will be conatining below
1)HTML will be containing ng-view and ng-template which will be used by routeProvide
2)One of the js files will be containing routeProvider Info to map the ng-template with view
Please correct me if this is right approach ?
Use AngularJS for data-binding and form-validation. When you want to submit a form, you can rely on jQuery:
<div ng-controller="ctrl">
<form id="myform" name="myform">
Name: <input type="text" ng-model="person.name" name="person.name" /> <br />
<button ng-click="submit(person)">Submit</button>
</form>
</div>
Script
app.controller('ctrl', function($scope) {
$scope.submit = function(person) {
if ($scope.myform.$valid) {
$('#myform').submit();
}
}
});
For this to work, make sure you give your input fields properly scoped names so that it binds to your MVC models.
This approach does have its limitations. For example, input fields that use ngModel should not have any $formatters/$parsers which limits you to simple formats.
I was exactly looking for Single Page App with AngularJS which describes how you can have full fledged SPA web app using AngularJS(with features like router,controller,service etc) in a clear and succinct way

Post form without name preferably with JSoup

I am building an Android app and I want to post a html form that looks like this:
<form onsubmit="ShoutBox.postShout(); $('shout_data').value = ''; return false;">
Shout: <input type="text" id="shout_data" size="50"> -
<input type="submit" value="Shout Now!" id="shouting-status"></form>
I am using Jsoup in the rest of the application and I would preferably use it for this aswell.
I know about the .data(name, value) method, but since the html text and button don't have name attributes, that's not working. I can extract the field by using the ids and fill the field with: Element.val(String val); But I don't know how to post the form after that. Can anyone help me?
This is the JavaScript code for posting it:
postShout: function() {
message = $("shout_data").value;
if (message == "") {
return false;
}
$("shouting-status").value = ShoutBox.lang[0];
postData = "shout_data="+encodeURIComponent(message).replace(/\+/g, "%2B");
new Ajax.Request('xmlhttp.php?action=add_shout', {method: 'post', postBody: postData, onComplete: function(request) { ShoutBox.postedShout(request); }});
},
The post is not done via a form submit and post variables but via JavaScript and an XML HTTP request. JSoup is incapable to execute JavaScript. You need a browser that you can remote control. To do this headless in Java HTMLUnit is a good choice.

Dojo ajax call returns before Java code completes?

I have a problem with a Struts2 + dojo web application that I've inherited. The application works in IE9 and Firefox but does not work in Chrome.
Here is the submit button code:
<button dojoType="dijit.form.Button"
type="submit"
onclick="sendRuleForm('requestSubmitForm', 'resultDiv', 'RequestSubmit.action');">Submit</button>
Here is the javascript code for the sendRuleForm function above:
function sendRuleForm(formId, id, actionNm) {
var bindArgs = {
url: actionNm,
form: document.getElementById(formId),
handleAs: "text",
load: function(data) {
document.getElementById(id).innerHTML = data;
},
error: function(data) {
alert(data);
return;
}
}
dojo.xhrPost(bindArgs);
document.getElementById(id).innerHTML = ajaxLoader;
}
I noticed that if I set breakpoints in my Java code, the web page returns with an error even before the action even completes.
Chrome Developer Tools indicate a status of cancelled for the action/request ( What does status=canceled for a resource mean in Chrome Developer Tools? )
I am using an older version of dojo 1.3.1 but updating it to the latest version did not fix the problem.
Can anyone explain this behavior and let me know how I can go about fixing this?
You can rule out the ajax / javascript bit of this error. It is either
a bug in chrome (unlikely)
a bug in the struts page youre calling, may send back a weird HTTP response (check server logs)
there's a 'jitter' in form submission, where multiple requests are sent. im guessing, but maybe <button type="submit" and <input type="submit" is handled differently in chrome
What youre experiencing in the redirect to a different page is probably due to the fact that Struts Application receives a GET when you manually refresh the URL field in the new tab. Could also be due to a missing login-cookie or such.
To have a true response from the application, try put in the target attribute with your form and then submit in a normal fashion (without XHR).
<form action="RequestSubmit.action" method="POST" target="_debugwin">
<input type="submit" value="DebugSubmit" name="debugbutton" />
... remainder of form code
Also, your dijit Button has an overridable function 'onClick', note the camelCasing. Youre setting the DOM onclick event. In this case, youre click event may get handled by the browser immediately after the dojo.xhr fires (when function returns). See this Q: Preventing form submission with Dojo
Only way, however, for this to be the case - and at same time you seeing the 'Cancelled' error in debug window is, if the form is loaded in a (i)frame. Otherwise the full page would refresh and network monitoring would reset. As an easy, win-win workaround, adapt the onclick attribute as follows:
<button dojoType="dijit.form.Button"
type="submit"
onClick="sendRuleForm('requestSubmitForm', 'resultDiv', 'RequestSubmit.action'); /* NOTE */ return false;">Submit</button>

Play! framework form redirect not working

I´m having a problem redirecting from a play! form. I think the problem lies in how I´m handling the routes. The idea is that a user should be able to go to dashboard.html either by going first through index.hmtl using login from with a secruity key, or by typing directly in a valid path containing an access_token (using a qr-code redirection)
What I´m trying to do is as follows:
1) login using a form on index.html (route: Application.index)
Here is my form (located in index.html):
<form action="#{Dashboard.authenticate()}" method="POST" name="login">
<input name="key" type="password" maxlength="128" value="${flash.key}">
<input class="button" id="btnLogin" type="submit" value="Login">
</form>
2) authenticate and redirect to dashboard.html (route: Dashboard.dashboard)
public static void dashboard(String access_token) {
/*
...some code
*/
render(username);
}
public static void authenticate(String key) {
/*
...some code
*/
dashboard(access_token);
}
Here is my route file:
# Home page
GET / Application.index
POST /dashboard Dashboard.authenticate
GET /dashboard Dashboard.dashboard
The dashboard route works fine if I call directly upon dashboard(String access_token) through an URL like: http://localhost:9000/dashboard?access_token=0000
But if i try to login using the login form that calls upon authenticate(String key) I get this URL http://localhost:9000/dashboard?access_token&key=1234 where key is the var being sent to the auth()function. Clearly my fault lies with the routes, but I have tried and tested the logic and I am 100% certain it is sound.
I´m using Play 1.2.4
I have spent two days on this problem and would be most grateful for any suggestions.
That actually seems like a bug. Maybe try
redirect("/dashboard?access_token="+access_token);
instead of
dashboard(access_token);
The Java code seems fine. Just in case, have you tried to change the routes file to:
# Home page
GET / Application.index
GET /dashboard Dashboard.dashboard
POST /dashboard Dashboard.authenticate
moving the GET before the POST (order matters, this should fix it if there is a Play bug on that section).
Another option is to simply rename the POST route, to fix the issue if it's caused by both routes having the same 'path'.
# Home page
GET / Application.index
GET /dashboard Dashboard.dashboard
POST /dashboard/auth Dashboard.authenticate
Problem Solved!
What I forgot to mention...oops was that I am also using jQuery Mobile and the problem had to do with Play! routing being overriden my jQuery Mobile page routing.
I disabled the routing by adding the following script:
$(document).bind("mobileinit", function(){
$.mobile.ajaxEnabled = false;
$.mobile.linkBindingEnabled = false;
$.mobile.hashListeningEnabled = false;
$.mobile.pushStateEnabled = false;
$.mobile.changePage.defaults.changeHash = false;
})
Using instructions on the jQuery website: http://jquerymobile.com/test/docs/api/globalconfig.html I implemented the above but the script needs to referenced in the .hmtml header in the following order:
<script src="jquery.js"></script>
<script src="custom-scripting.js"></script>
<script src="jquery-mobile.js"></script>

Jsoup posting modified Document

I'm trying to create a web scraper for my coming android app. Therefore I need to use a simple search form on a website, fill it out and send my results back to the server.
As mentioned in the Jsoup-Cookbook, I scraped the site I needed from the Server and changed the values.
Now I just need to post my modified document back to the server and scrape the resulting page.
As far as I've seen in the Jsoup-API there is no way to post something back, except with the .data-Attribute in Jsoup.connection, which is unfortunately not able to fill out text fields by their id.
Any ideas or workarounds, how to post the modified document, or its parts back to the website ?
You seem to misunderstand how HTTP works in general. It is not true that the entire HTML document with modified input values is been sent from the client to the server. It's more so that the name=value pairs of all input elements are been sent as request parameters. The server will return the desired HTML response then.
For example, if you want to simulate a submit of the following form in Jsoup (you can find the exact HTML form syntax by opening the page with the form in your browser and do a rightclick, View Source)
<form method="post" action="http://example.com/somescript">
<input type="text" name="text1" />
<input type="text" name="text2" />
<input type="hidden" name="hidden1" value="hidden1value" />
<input type="submit" name="button1" value="Submit" />
<input type="submit" name="button2" value="Other button" />
</form>
then you need to construct the request as follows:
Document document = Jsoup.connect("http://example.com/somescript")
.data("text1", "yourText1Value") // Fill the first input field.
.data("text2", "yourText2Value") // Fill the second input field.
.data("hidden1", "hidden1value") // You need to keep it unmodified!
.data("button1", "Submit") // This way the server knows which button was pressed.
.post();
// ...
In some cases you'd also need to send the session cookies back, but that's a subject apart (and a question which has already been asked several times here before; in general, it's easier to use a real HTTP client for this and pass its response through Jsoup#parse()).
See also:
HTTP tutorial
HTTP specification
That's not the way. You should create a POST request (use Apache HTTP Components), get the response and then scrape it with JSoup.

Categories

Resources