how can i pass a JSON Array/Object with the JQUERY get Method to my Java Servlet?
So far , here's my code:
var json = {
MA_ID : $("#emplID").val(),
MA_Nachname : $("#nachname").val()
}
$.get(url + "/MA_Update", json)
[...]
MA_Update.java
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
StringBuffer jb = new StringBuffer();
String line = null;
BufferedReader reader = request.getReader();
while ((line = reader.readLine()) != null) {
jb.append(line);
}
try {
JSONObject jsonObject = HTTP.toJSONObject(jb.toString());
System.out.println(jsonObject);
} catch (JSONException e) {
// crash and burn
throw new IOException("Error parsing JSON request string");
}
}
But I only get
{"Request-URI":"","Method":"","HTTP-Version":""}
from my request
Do not use request.getReader(), use request.getParameter("MA_ID") etc., or request.getParameterMap() (and iterate over it).
The thing is, that $.get(url, jsObject) creates a HTTP GET request, where the fields of the jsObject are transformed into query parameters, i.e. http://your.server.com/MA_Update?MA_ID=someID&MA_Nachname=SomeLastName, so they are NOT available in the request body (as they would be in a POST request).
Related
I have a situation in which I want to select all records from a database given a specific id. The request is first sent from JavaScript, which is received by a Servlet which accesses a DAO that in turn queries a database. The data will then, obviously, make its way back to the front-end. I'm just a little cloudy on passing these parameters along so that the database is queried correctly.
I am currently getting a 500 error which is due to my parameters not being passed along correctly.
Starting at the JavaScript with the initial request:
let xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:8080/project1attempt/reimbursement?
employee_id=' + x._id, true);
xhr.send();
Receiving the parameters at the Servlet is my biggest point of confusion, therefore the code here is incomplete (rs is a Reimbursement Service):
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("application/json");
int id = ;
List<Reimbursement> reimbursements = rs.findAllReimbursements(id);
String json = new ObjectMapper().writeValueAsString(reimbursements);
resp.getWriter().write(json);
}
And the query:
public List<Reimbursement> findAllReimbursements(int id) {
List<Reimbursement> reimbursements = new ArrayList<>();
try
(Connection c = manager.getConnection()) {
String sql = "SELECT reimbursement_id, date, description, amount,
typing_id, employee_id" +
"FROM reimbursements" +
"WHERE reimbursement_id = ?";
PreparedStatement ps = c.prepareStatement(sql);
ps.setInt(1, id);
ResultSet rs = ps.executeQuery();
Reimbursement r = null;
while (rs.next()) {
r = new Reimbursement();
r.setId(rs.getInt("reimbursement_id"));
r.setDate(rs.getDate("date"));
r.setDescription(rs.getString("description"));
r.setAmount(rs.getDouble("amount"));
r.setTypingId(rs.getInt("typing_id"));
r.setEmployeeId(rs.getInt("employee_id"));
reimbursements.add(r);
}
return reimbursements;
} catch (SQLException e) {
throw new BlabApplicationDataException("Could not connect to
Reimbursement Repository" + id);
}
}
You can use getParameter method of HttpServletRequest to get the URL parameter you need.
Probably, this is the line you are looking for.
String idStr = req.getParameter('employee_id');
if(idStr != null) {
int id = Integer.parseInt(idStr);
}
I am working with Spring and javascript. Calling #Controller with XhrHttpRequest Object.
I can see my parameter(JSON string) with Chrome Inspector, but when I call request.getParamter("id") returns null.
Calling part with js
function ajax(url, data, callback, method){
//data is {"id":"system", "password" : "1234"}
var httpRequest;
var afterAction = function(){
if(!httpRequest) {
console.error('can not find httpRequest variable');
return;
}
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
var responseData = httpRequest.responseText;
//alert(JSON.stringify(responseData));
console.log('Result of API call >>>', responseData);
if(typeof callback == 'function') {
callback(JSON.parse(responseData));
}
} else {
alert('There was a problem with the request.');
}
}
}
//=========== LOGIC ============
if (window.XMLHttpRequest) { // Mozilla, Safari, IE7+ ...
httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE 6 and older
httpRequest = new ActiveXObject('Microsoft.XMLHTTP');
}
if(!method) method = 'POST';
data = (!!data) ? JSON.stringify(data) : '';
httpRequest.onreadystatechange = afterAction;
httpRequest.open(method.toUpperCase(), url, true);
httpRequest.setRequestHeader("Content-type", "application/json; charset=utf-8");
//httpRequest.setRequestHeader("Content-length", data.length);
//httpRequest.setRequestHeader("Connection", "close");
httpRequest.send(data);
}
receive part with Spring #Controller
#Controller
#RequestMapping(value={"member"}, produces={"application/json"})
#ResponseStatus(value = HttpStatus.OK)
public class MemberController {
/**
* #param request
* #param resp
* #return
* #throws Exception
*/
#RequestMapping(value={"/login"})
public #ResponseBody String login(HttpServletRequest request, HttpServletResponse resp) throws Exception {
System.out.println("Login request");
String id = String.valueOf(request.getParameter("id")); //returns null
String password = String.valueOf(request.getParameter("password")); //returns null
Map<String, String> result = new HashMap<String, String>();
result.put("result", "S");
result.put("message", "login success");
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(result);
}
}
I do not know why parameter becomes null. Thanks.
You need to follow the below steps to accept Json in your controller:
(1) Define UserLogin bean to hold the Json
public class UserLogin {
private String id;
private String password;
//Add getters and setters
}
(2) Change your controller to accept Json & receive the UserLogin bean
#Controller
#RequestMapping(value={"member"}, produces={"application/json"})
#ResponseStatus(value = HttpStatus.OK)
public class MemberController {
#RequestMapping(value={"/login"}, method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody String login(UserLogin userLogin) throws Exception {
System.out.println("Login request");
String id = userLogin.getId();
String password = userLogin.getPassword();
Map<String, String> result = new HashMap<String, String>();
result.put("result", "S");
result.put("message", "login success");
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(result);
}
}
This is an Alternative way with Jackson Library. I like #javaguy 's way, but using Jackson library could be more flexible so add this post.
Preparations
WebMvcConfigurerAdapter implements class or something equivalent with that
SpringFramework Environment. In my case, Eclipse Dynamic Web Project with Maven and spring-webmvc in pom.xml.
What I did...
Implement WebMvcConfigurerAdapter
Override Method configureMessageConverters
Change Controller parameters from HttpServeletRequest request, HttpServletResponse resp to #RequestBody Map<?, ?>.(You can change generic value. It does not matters for further process)
So Here's code.
ServerConfig.java (I block other Options to focus current issue)
#Configuration
#EnableWebMvc
#ComponentScan(basePackages={ ... }
, excludeFilters=#ComponentScan.Filter(Configuration.class))
//Filter 걸 때 Configuration.class 를 수동으로 등록해줘야 되는데 나은 방법 찾아보기
public class ServerConfig extends WebMvcConfigurerAdapter {
...
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter());
super.configureMessageConverters(converters);
}
};
And Controller (Change Parameter Types)
#Controller
#RequestMapping(value={"member"}, produces={"application/json"})
#ResponseStatus(value = HttpStatus.OK)
public class MemberApiController {
...
#RequestMapping(value={"/login"})
public #ResponseBody String login(#RequestBody Map<?, ?> jsonBody) throws JsonProcessingException {
System.out.println("Login request" + jsonBody.toString());
Map<String, String> result = new HashMap<String, String>();
String rs = "S";
String message = "SUCCESS";
System.out.println("ID >>> ", String.valueOf(jsonBody.get("id")));
System.out.println("PW >>> ", String.valueOf(jsonBody.get("password")));
result.put("result", rs);
result.put("result_msg", message);
mapper = new ObjectMapper();
return mapper.writeValueAsString(result);
}
};
However, since as far as I know #RequestBody does not have HttpSession, If you try to store data to HttpSession, you need another parameter HttpServletRequest.
I hope this could be a hand to others who has same problem with me :D
I am developing a client-server app with a JavaScript client and a Java Servlet running in Apache Tomcat. I am developing both ends, so I hope to do things the "right" way.
My JavaScript uses XMLHttpRequest. It seems like XMLHttpRequest does not do caching for me, so I used IndexedDB to cache responses. IndexDB is working sweetly for me in all the browsers I need to support (iOS, Android, PC, Mac).
I really want to manage cache validity with ETag values, so I tried this...
public class MyServlet_Etag extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String etag = myEtag(request);
String inm = request.getHeader("If-None-Match");
if (inm != null && inm.equals(etag))
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
else {
byte[] data = myData(request);
response.setHeader("ETag", etag);
response.getOutputStream().write(data);
response.setContentLength(data.length);
response.setContentType("application/octet-stream");
response.setStatus(HttpServletResponse.SC_OK);
}
}
}
... but Tomcat strips out my "ETag" headers. So I tried this...
public class MyServlet_LastModified extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
byte[] data = myData(request);
response.getOutputStream().write(data);
response.setContentLength(data.length);
response.setContentType("application/octet-stream");
response.setStatus(HttpServletResponse.SC_OK);
}
#Override
protected long getLastModified(HttpServletRequest request) {
return myLastModified(request);
}
}
The above Servlet code is simple, and in JavaScript I can manage my IndexedDB cache with the following code:
refreshURI = function(uri,lastModified,onRead) {
var req = new XMLHttpRequest();
req.open("GET", uri, true);
req.responseType = "arraybuffer";
req.setRequestHeader("If-Modified-Since", lastModified);
var _this = this;
req.onreadystatechange = function () {
if (req.readyState == 4) {
var hundred = Math.floor(req.status / 100);
if (hundred == 2) {
var response = req.response;
var lastModified = req.getResponseHeader("Last-Modified");
myIndexedDB.write(uri, req.response, lastModified);// Update our cache
onRead(response, lastModified);
} else if (hundred == 3) {
// No recent change, so skip further processing
}
}
};
};
So my app is working. But it can only handle 1 update per second, because the Last-Modified resolution is 1 second in HTTP's date format. I want to support many updates per second. I could use fake Last-Modified values that update by 1 second each update. But this is not the "right" way!
Q1. Is there some way to stop Tomcat stripping out my ETag values?
Q2. Is it acceptable to use fake Last-Modified HTTP header values between my JavaScript and my Servlet?
Q3. What is the right way to cache HTTP responses between a JavaScipt client and a Java Servlet?
I am attempting to pass a PDF I have generated on frontend javascript using jsPDF to a Spring Framework MVC backend. Below is the front end code I have written:
var filename = "thefile";
var constructURL = '/daas-rest-services/dashboard/pdfPrintUpload/' + filename;
var url = restService.getUrl(constructURL);
var fileBytes = btoa(pdf.output());
$http.post(url, fileBytes).success(function(data) {
console.log(data);
})
.error(function(e, a) {
console.log(e);
console.log(a);
});
The pdf variable has been generated properly and can confirm is opens correctly when calling pdf.save("filename"). Below is the Java code which has been written on the Spring MVC backend for this call:
#RequestMapping(method = RequestMethod.POST, value = "/pdfPrintUpload/{documentName}")
public #ResponseBody String postPrintDocument(#PathVariable String documentName, #RequestParam byte[] fileBytes) {
String methodName = "postPrintDocument";
if(logger.isLoggable(Level.FINER)){
logger.entering(CLASS_NAME, methodName);
}
String check;
if(fileBytes != null){
check = "not null";
} else {
check = "null ";
}
//Decoding the bytestream
//Save to file location
//return file location
String returnValue = "HI " + documentName + " " + check;
if (logger.isLoggable(Level.FINER)) {
logger.exiting(CLASS_NAME, methodName);
}
return returnValue;
}
Each time I make a request, I am getting 400 Errors telling me:
Error 400: Required byte[] parameter 'fileBytes' is not present
I can confirm in the request payload that a large amount of data is being transmitted, however the backend does not seem to want to accept the parameter.
The purpose of doing this is that I want to be able to get the data from the pdf and then decode it on the backend so I can later publish the pdf to a location on the server. Is there something I am missing in my code for these requests to keep failing, and is there an easier more efficient way to achieve this functionality?
The solution was changing the #RequestParam to #RequestBody. #RequestParam is a parameter which is sent in the path.
#RequestParam vs #PathVariable
Try using ng-file-upload. The link and the examples are available on the link
ng-file-upload
for the sever side code try using this
#RequestMapping(value = "/pdfPrintUpload")
#ResponseBody
public void postPrintDocument(#RequestParam("file") MultipartFile file) {
InputStream is = file.getInputStream();
OutputStream os = new FileOutputStream(/*path to save file*/);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0)
os.write(buffer, 0, length);
is.close();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
The process is this:
from web(jsp) I upload some pdf file(submitting via ajax)
in the backend I merge these pdf
I get the response(the merged pdf) via ajax --> start the file download...
I'm having issues with the third step.
I've included only the relevant code where I submit the file to upload (post request) and start the download.
I put also a direct link, that calls the same steps in get method and works.
Where is my problem?
Thanks in advance...
Here is the jsp body tag
<a href="/TestAjaxServletDownload/DownloadServlet" >
download
</a>
<p><input id="sampleFile5" name="sampleFile5" type="file" /></p>
<p><input id="uploadBtn" type="button" value="Upload" onClick="javascript:performAjaxSubmit();"></input></p>
Here is my javascript tag content
function performAjaxSubmit() {
var sampleFile1 = document.getElementById("sampleFile5").files[0];
var formdata = new FormData();
formdata.append("sampleFile", sampleFile1);
var xhr = new XMLHttpRequest();
xhr.onload = function() {
if(xhr.readyState == 4 && xhr.status == 200) {
// alert("ok..." + xhr.responseText);
//?????????????????????????????
document.location=xhr.responseText;
}
};
xhr.open("POST","/TestAjaxServletDownload/DownloadServlet", true);
xhr.send(formdata);
}
Here is my web.xml servelet mapping tags
<servlet>
<description></description>
<display-name>DownloadServlet</display-name>
<servlet-name>DownloadServlet</servlet-name>
<servlet-class>test.DownloadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DownloadServlet</servlet-name>
<url-pattern>/DownloadServlet</url-pattern>
</servlet-mapping>
Here is my servlet code
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("DO GET SERVLET MERGE");
execute (request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
System.out.println("DO POST SERVLET MERGE");
execute (request, response);
}
protected void execute(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
File downloadFile = new File("c:\\data\\example.pdf");
System.out.println("++++" + downloadFile.getAbsolutePath());
// System.out.println(uploadPathTemp+mergeFileName);
FileInputStream inStream = new FileInputStream(downloadFile);
// obtains ServletContext
ServletContext context = getServletContext();
// gets MIME type of the file
String mimeType = context.getMimeType(downloadFile.getCanonicalPath());
if (mimeType == null) {
// set to binary type if MIME mapping not found
mimeType = "application/octet-stream";
}
// modifies response
response.setContentType(mimeType);
response.setContentLength((int) downloadFile.length());
// forces download
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"", downloadFile.getName());
System.out.println(downloadFile.getName());
response.setHeader(headerKey, headerValue);
// obtains response's output stream
OutputStream outStream = response.getOutputStream();
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
inStream.close();
outStream.close();
}
What about changing
<a href="/TestAjaxServletDownload/DownloadServlet" >
download
</a>
to
<a id="pdfLink" href="/TestAjaxServletDownload/DownloadServlet" >
download
</a>
and then use document.getElementById('pdfLink').click()?