How to get parametr in response from spring? (rest Javascript) - javascript

I have a problem with returning an error to html. So, I have web-app with "sql interpreter".
HTML
<button type="submit" onclick="executeSQL('interpreterSQL')">
<i class="fas fa-bolt"></i>
</button>
<textarea id="interpreterSQL" placeholder="❔❔❔"></textarea>
After entering a query into the interpreter, I run POST in javascript and shoot to spring:
POST in JavaScript
function executeSQL(interpreterSQL) {
var tmp = document.getElementById(interpreterSQL).value;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// Typical action to be performed when the document is ready:
var response = xhttp.responseText;
console.log("ok"+response);
}
};
xhttp.open("POST", "/user/executeSQL", true);
xhttp.send(tmp);
}
After that I handle the query in my service and return message to POST in my Controller:
Controller (POST in Spring)
#PostMapping(path = { "/user/executeSQL" })
public ModelAndView executeSQL(#RequestBody String tmp) {
String[] split = tmp.replace("\n", "").replace("\t", "").split(";");
String feedback = databaseTableService.executeSQL(split);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("successMessage", feedback);
modelAndView.setViewName("/user/interpreterSQL");
return modelAndView;
}
Service which is used to execute native query
public String executeSQL(String[] split){
SessionFactory hibernateFactory = someService.getHibernateFactory();
Session session = hibernateFactory.openSession();
String message = null;
for (int i = 0; i < split.length; i++) {
try{
String query = split[i];
session.doWork(connection -> connection.prepareStatement(query).execute());
message = "Success";
}
catch(Exception e){
message = ((SQLGrammarException) e).getSQLException().getMessage();
}
}
session.close();
return message;
}
So finally we are in my controller which is ready to return value and we have message which is have information about sql exceptions. We are there:
And here is my question: How to get variable "feedback" in response?
I need to handle that value there i think:
but that "var response = xhttp.responseText" is returning all my HTML code. I need only parametr "feedback" from my controller.
Guys can someone help? :( I don't know how to send that parametr in return and handle it in javascript...

Maybe you can change your Controler method to return JSON response instead on ModelAndView
#PostMapping(path = { "/user/executeSQL" })
public ResponseEntity<Object> executeSQL(#RequestBody String tmp) {
String[] split = tmp.replace("\n", "").replace("\t", "").split(";");
Map<String,String> response = new HashMap<String, String>();
response.put("feedback", databaseTableService.executeSQL(split));
return new ResponseEntity<>( response , HttpStatus.OK);
}
Now you should be able to see the status
var response = xhttp.responseText;
console.log("ok"+response);

Related

Android Capacitor JS Plugin does not reply

I am working on a java plugin that is supposed to recieve some info from a js vue3 program and then do a URL post operation, and then return some of the info found back to the js code. I am using capacitor and android. This is my error message:
2022-08-22 13:46:23.773 27544-27544/org.theguy.GptEtc E/Capacitor/Console: File: http://localhost/js/app.6577adf2.js - Line 1 - Msg: Uncaught (in promise) SyntaxError: Unexpected token o in JSON at position 1
I think this means that something other than valid JSON is being delivered to the js code. I know that the app is delivering info to the java android class. This is some of my java code.
#CapacitorPlugin(name = "URLPOST")
public class PluginURLPost extends Plugin {
#PluginMethod()
public void post(PluginCall call) {
String post_url = call.getString("post_url", "");
String bearer = call.getString("bearer", "pipeline_");
JSObject ret = new JSObject();
try {
String value = this.doPost(post_url, bearer);
System.out.println("value " + value);
Gson gson = new Gson();
JsonReader reader = new JsonReader(new StringReader(value));
ResultPreview preview = gson.fromJson(reader, ResultPreview.class);
String val = preview.getResult_preview()[0][0];
val = "result string here."; // <-- add this for easy testing
ret.put("response_text", val.replace("\n", "\\n"));
System.out.println("response here: " + val);
}
catch (Exception e) {
e.printStackTrace();
}
//call.setKeepAlive(true);
call.resolve(ret);
}
OkHttpClient client = new OkHttpClient();
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
String doPost(String post_url, String bearer ) throws IOException {
// ... do some post request here ...
return response_body;
}
}
class ResultPreview {
#SerializedName("result_preview")
String [][] result_preview ;
public void setResult_preview(String[][] result) {
this.result_preview = result;
}
public String[][] getResult_preview() {
return this.result_preview;
}
}
This is some of my js code.
import { registerPlugin } from "#capacitor/core";
const URLPOST = registerPlugin("URLPOST");
const request = {
"line": line,
"pipeline_model": details[engine]["app_model"].trim(),
"bearer": details[engine]["api_key"].trim(),
"post_url": details[engine]["url"].trim(),
"length": 25,
"top_k": 50
};
console.log("request", request);
var {response_text} = await URLPOST.post(request);
console.log("response_text 1",response_text);
I don't know what to do.
I tried this, and things work better. I don't know if this is the ultimate solution.
#PluginMethod()
public void post(PluginCall call) {
bridge.saveCall(call); // <-- add this
call.release(bridge); // <-- add this
String pipeline_model = call.getString("pipeline_model", "pipeline_");
String post_url = call.getString("post_url", "");
JSObject ret = new JSObject();
try {
String value = this.doPost(post_url);
Gson gson = new Gson();
JsonReader reader = new JsonReader(new StringReader(value));
ResultPreview preview = gson.fromJson(reader, ResultPreview.class);
String val = preview.getResult_preview()[0][0];
ret.put("response_text", val.replace("\n", "\\n"));
System.out.println("response here: " + val);
}
catch (Exception e) {
e.printStackTrace();
}
call.resolve(ret);
}
This is not found on the capacitor site, but instead I found it digging around the internet.

converting a piece of javascript code to c# access API

I need a C# code that will trigger a nprinting task. On our server we are not allowed to evoke html file, hence I can't use javascript attached.
The attached works just need to translate it to .net as I can't use html on our server
Javascripts below works just fine
<html>
<head>
</head>
<body>
<h1>NPrinting API task starter</h1>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript">
(function(){
console.log("started")
var taskIDs=[
"f3ebd873-b310-4a22-a269-24ce81b8ce74"
]
$.ajax({
url: 'URL:4993/api/v1/login/ntlm',
xhrFields: {
withCredentials: true
}
}).done(function(data) {
console.log(data);
for(var i=0;i<taskIDs.length;i++){
$.ajax({
type: "POST",
url: 'URL:4993/api/v1/tasks/'+taskIDs[i]+'/executions',
xhrFields: {
withCredentials: true
}
}).done(function(data) {
console.log("task "+i);
console.log(data);
if(i==taskIDs.length)
open(location, '_self').close();
});
}
});
})();
<!-- open(location, '_self').close(); -->
</script>
</body>
</html>
C# code which I can't complete all the below works but doesn't start the task.
//Create the HTTP Request (authenticate) and add required headers
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL:4993/api/v1/login/ntlm");
CookieContainer cookies = new CookieContainer();
request.CookieContainer = cookies;
request.Method = "GET";
request.UserAgent = "Windows";
request.Accept = "application/json";
// specify to run as the current Microsoft Windows user
request.UseDefaultCredentials = true;
try
{
// make the web request and return the content
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader responseReader = new StreamReader(response.GetResponseStream());
string sResponseHTML = responseReader.ReadToEnd();
Console.WriteLine(sResponseHTML);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
//Create second HTTP request (get list of apps) and add required headers
HttpWebRequest secondRequest = (HttpWebRequest)WebRequest.Create(#"URL:4993/api/v1/tasks/f3ebd873-b310-4a22-a269-24ce81b8ce74/executions");
//assign cookie to request to maintain session
secondRequest.CookieContainer = cookies;
secondRequest.Method = "POST";
secondRequest.UserAgent = "Windows";
secondRequest.Accept = "application/json";
// specify to run as the current Microsoft Windows user
secondRequest.UseDefaultCredentials = true;
Thanks
I found a solution to the above, request.
Nprinting API task to run from C#
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace Post_Request_API
{
class Program
{
static void Main(string[] args)
{
//Create the HTTP Request (authenticate) and add required headers
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(#"URL:4993/api/v1/login/ntlm");
//Assign custom SSL certificate validation method if certificate is untrusted
//request.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
CookieContainer cookies = new CookieContainer();
request.CookieContainer = cookies;
request.Method = "GET";
request.UserAgent = "Windows";
request.Accept = "application/json";
//Specify to run as the current Microsoft Windows user
request.UseDefaultCredentials = true;
try
{
// make the web request and return the content
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader responseReader = new StreamReader(response.GetResponseStream());
string sResponseHTML = responseReader.ReadToEnd();
Console.WriteLine(sResponseHTML);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
//Create second HTTP request to add a new user and required headers
HttpWebRequest secondRequest = (HttpWebRequest)WebRequest.Create(#"URL:4993/api/v1/tasks/f3ebd873-b310-4a22-a269-24ce81b8ce74/executions");
//Assign custom SSL certificate validation method if certificate is untrusted
//secondRequest.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
//Add the XSRF token
secondRequest.Headers.Add("X-XSRF-TOKEN", cookies.GetCookies(request.RequestUri)["NPWEBCONSOLE_XSRF-TOKEN"].Value);
secondRequest.CookieContainer = cookies;
secondRequest.Method = "POST";
secondRequest.UserAgent = "Windows";
secondRequest.Accept = "application/json";
secondRequest.ContentType = "application/json";
//Specify to run as the current Microsoft Windows user
secondRequest.UseDefaultCredentials = true;
//Prepare JSON object to send to the remote server
JsonUser user = new JsonUser();
user.ID = "";
user.type = "";
user.task = "";
user.created = "";
user.lastUpdate = "";
user.completed = "";
user.progress = "";
user.status = "Enqueued";
user.result = "";
user.priority = "";
string jUserString = JsonConvert.SerializeObject(user);
using (var streamWriter = new StreamWriter(secondRequest.GetRequestStream()))
{
streamWriter.Write(jUserString);
streamWriter.Flush();
streamWriter.Close();
}
try
{
HttpWebResponse response2 = (HttpWebResponse)secondRequest.GetResponse();
StreamReader responseReader2 = new StreamReader(response2.GetResponseStream());
string sResponseHTML2 = responseReader2.ReadToEnd();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public class JsonUser
{
public string ID { get; set; }
public string type { get; set; }
public string task { get; set; }
public string created { get; set; }
public string lastUpdate { get; set; }
public string completed { get; set; }
public string progress { get; set; }
public string status { get; set; }
public string result { get; set; }
public string priority { get; set; }
}
}
}

UTF-8 characters messed up after POST request in ASP.NET Core

I'm using ASP.NET Core MVC.
I'm trying to make a POST request to a Controller with FormData. But, if I put Arabic letters in the FormData to send to the Controller, it receives it as question marks.
I tried changing the Content-Type but then nothing sends at all.
This is how I send the POST request:
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
window.location.href = 'Categories';
}
}
xhr.open("POST", 'http://localhost:52320/api/Categories/Add', true);
const fd = new FormData();
fd.append('CatName', txtCatName.value);
fd.append('FileName', uploadFileName);
xhr.send(fd);
and this is how I receive it in the Controller:
[Route("api/[controller]")]
public class CategoriesController : Controller {
[Route("Add")]
[HttpPost]
public IActionResult Add(FormData formData)
{
if (formData != null && ModelState.IsValid)
{
DataManager.Instance.AddCategory(formData.CatName, formData.FileName);
return Ok();
}
return BadRequest();
}
}
public class FormData
{
public string CatName { get; set; }
public string FileName { get; set; }
}
Solved.
The problem was inserting into SQL, actually. I thought it had been enough to make the column NVARCHAR but apparently I had to use N before the string.
Thanks to everyone in the comments for helping me out! It was useful.

Server Sent Events with AJAX: How to resolve SSE GET with XHR POST?

I'm trying to resolve an issue between, what I perceive is, AJAX and Server Sent Events. I have an application that does a post with some instructions to the controller, and I would like the controller to send some commentary back as an event to let the user know that the action requested has been performed (can have errors or take a while).
The idea is that the user can send a package of different instructions through the client, and the server will report through SSE when each of these actions are completed.
The problem I see through Fiddler is that when the post is performed, the response that it gets back contains my eventsource message that I would like used. However, the eventsource code also appears to call a GET, in which it appears to want that eventsource message. Because it doesn't get that, the connection repeatedly closes.
I currently have some controller code like so:
[System.Web.Http.HttpPost]
public void Stop(ProjectViewModel model)
{
ProjectManager manager = new ProjectManager();
if (model.Servers != null && model.Servers.Count != 0)
{
string machine = model.Servers[0];
foreach (string service in model.Services)
{
manager.StopService(service, machine);
Message("stop", service);
}
}
}
and in my view, both Ajax/XHR and server sent events set up like so:
var form = document.getElementById("submitform");
form.onsubmit = function (e) {
// stop the regular form submission
e.preventDefault();
// collect the form data while iterating over the inputs
var data = {};
for (var i = 0, ii = 2; i < ii; ++i) {
var input = form[i];
if (input.name == "Servers") {
data[input.name] = document.getElementById("ServerSelect").options[document.getElementById("ServerSelect").selectedIndex].text;
}
else if (input.name == "Services")
data[input.name] = document.getElementById("ServiceSelect").options[document.getElementById("ServiceSelect").selectedIndex].text;
}
if (action) { data["action"] = action };
// construct an HTTP request
var xhr = new XMLHttpRequest();
if (action == "stop") {
xhr.open(form.method, '/tools/project/stop', true);
}
if (action == "start") {
xhr.open(form.method, '/tools/project/start', true)
}
xhr.setRequestHeader('Content-Type', 'application/json; charset=urf-8');
// send the collected data as JSON
xhr.send(JSON.stringify(data));
xhr.onloadend = function () {
// done
};
};
function events() {
if (window.EventSource == undefined) {
// If not supported
document.getElementById('eventlog').innerHTML = "Your browser doesn't support Server Sent Events.";
} else {
var source = new EventSource('../tools/project/Stop');
source.addEventListener("message", function (message) { console.log(message.data) });
source.onopen = function (event) {
document.getElementById('eventlog').innerHTML += 'Connection Opened.<br>';
console.log("Open");
};
source.onerror = function (event) {
if (event.eventPhase == EventSource.CLOSED) {
document.getElementById('eventlog').innerHTML += 'Connection Closed.<br>';
console.log("Close");
}
};
source.onmessage = function (event) {
//document.getElementById('eventlog').innerHTML += event.data + '<br>';
var newElement = document.createElement("li");
newElement.textContent = "message: " + event.data;
document.getElementById("eventlog").appendChild(newElement)
console.log("Message");
};
}
};
I'm somewhat new to web development, and I'm not sure how to resolve this issue. Is there a way I can have the eventsource message read from that POST? Or have it sent to the GET instead of being sent as a response to the POST? Overall, it seems that the most damning issue is that I can't seem to get the event messages sent to the GET that is requested by the eventsource api.
EDIT: Since posting this, I tried creating a new method in the controller that specifically handles eventsource requests, but it appears that the event response still somehow ends up in the POST response body.
public void Message(string action, string service)
{
Response.ContentType = "text/event-stream";
Response.CacheControl = "no-cache";
//Response.Write($"event: message\n");
if (action == "stop")
{
Response.Write($"data: <li> {service} has stopped </li>\n\n");
}
Response.Flush();
Thread.Sleep(1000);
Response.Close();
}
I ended up solving this. My original idea was to pass the viewmodel in each of my methods back and forth with a Dictionary<string,string> to key in each event that can be used, but the viewmodel is not persistent. I solved this issue further by implementing the events in a Dictionary saved in Session data, and the usage of Sessions for MVC can be found in the resource here that I used:
https://code.msdn.microsoft.com/How-to-create-and-access-447ada98
My final implementation looks like this:
public void Stop(ProjectViewModel model)
{
ProjectManager manager = new ProjectManager();
if (model.Servers != null && model.Servers.Count != 0)
{
string machine = model.Servers[0];
foreach (string service in model.Services)
{
manager.StopService(service, machine);
model.events.Add(service, "stopped");
this.Session["Events"] = model.events;
}
}
//return View(model);
}
public void Message(ProjectViewModel model)
{
Thread.Sleep(1000);
Response.ContentType = "text/event-stream";
Response.CacheControl = "no-cache";
Response.AddHeader("connection", "keep-alive");
var events = this.Session["Events"] as Dictionary<string, string>;
Response.Write($"event: message\n");
if (events != null && events.Count != 0)
{
foreach (KeyValuePair<string, string> message in events)
{
Response.Write($"data: {message.Key} has been {message.Value}\n\n");
}
}
Response.Flush();
Thread.Sleep(1000);
Response.Close();
}
Adding keep-alive as connection attribute in the HTTP Response header was also important to getting the SSEs to send, and the Thread.Sleep(1000)'s are used due to the stop action and message action happening simultaneously. I'm sure there's some optimizations that can go into this, but for now, this is functional and able to be further developed.

Login using Javascript and REST

I made a REST service, which will return a String "hej" if the log in is true.
I have tested in Java with a rest client and it works fine, but pretty new to javascript and need some help.
I'm using this function
function UserAction() {
console.log(User());
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "http://localhost:8080/Footballmanagerrestservice/webresources/login");
xhttp.setRequestHeader("login", User());
xhttp.responseType = 'text';
xhttp.onreadystatechange = function () {
console.log('DONE', xhttp.readyState);
if (xhttp.readyState == 4) {;
// handle response
var response = xhttp.responseText;
console.log(response);
if (response == "hej") {
var url = "http://localhost:8080/FM3/spil2.jsp";
window.location.href = url;
}
}
};
// send the request *after* the callback is defined
xhttp.send();
return false;
}
function User() {
username = document.getElementById("username").toString();
username = document.getElementById("password").toString();
var UserAndPass = "?username=" + username + "&password=" + password;
return UserAndPass;
}
I show you the client i have i Java, maybe you can see why it's not working.
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
String root="http://localhost:8080/Footballmanagerrestservice/webresources/";
String functionPath="login";
String parameters="?username=s153518&password=holger";
Response res = client.target(root+functionPath+parameters)
.request(MediaType.APPLICATION_JSON).get();
String svar = res.readEntity(String.class);
System.out.println(svar);
}
first part of the code looks ok, the following instead must be handled inside a function because is intrinsically asynchronous
var response = JSON.parse(xhttp.responseText);
console.log(response);
if (response.toString() == "hej") {
var url = "http://localhost:8080/FM3/spil2.jsp";
window.location.href = url
}
return false;
doc: https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest/onreadystatechange
essentially you're trying to handle the response as a syncrhonous call, but it's not, the response it's not immediatly avaiable, for this reason you have to register a callback (from the doc must be attached to the field onreadystatechange) that will be triggered by javascript as soon as the server response is available.
try to change it like so:
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {
// handle response
var response = JSON.parse(xhttp.responseText);
console.log(response);
if (response.toString() == "hej") {
var url = "http://localhost:8080/FM3/spil2.jsp";
window.location.href = url
}
}
}
xhr.send();

Categories

Resources