I use AJAX to fill a list asynchronously. Right after loading web page, an AJAX request to fill list box is triggered. But when I send this request to server, an unintended web page (on which the list box exists) is returned instead of list data(JSON).
[Components]
haveList.jsp = There is list box. It includes <script src="loadData.js"> tag.
loadData.js = It generates ajax request and send it to server. Right after loading haveList.jsp, loadData.js will be called. ( I'm just checking request get correct data from server using alert. )
returnPage.java = Servlet that forwards to haveList.jsp
returnJsonData.java = Servlet that returns json string that loadData.js asked for.
Each of these are shown below.
[web.xml]
<servlet>
<servlet-name>ReturnPage</servlet-name>
<servlet-class>pkg.ReturnPage</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ReturnPage</servlet-name>
<url-pattern>/openHaveList.do</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>DataManager</servlet-name>
<servlet-class>pkg.ReturnJsonData</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DataManager</servlet-name>
<url-pattern>/requestListData.do</url-pattern>
</servlet-mapping>
[Phenomenon]
I sent "openHaveList.do" to server.
Page "haveList" returned.
Immediately an AJAX request to get JSON data occurred. (requestListData.do) (Refer to loadData.js below)
Using alert() I checked the content of responseText from server
I expected JSON data, but the HTML of haveList.jsp was there.
[Clues]
(1) When I got unintended html from server, browser's address bar showed http://localhost/openHaveList.do
( In other page, I click image. Then openHaveList.do occured. )
(2) When I captured request/response using ZAP (Zed Attack Proxy), I saw 2 requests occurred.
The first : requestListData.do ( Response : empty )
The second : openHaveList.do. ( Response : html of haveList.jsp )
Because of this, I suspect AJAX request is redirected unintentionally. ( requestListData.do --> openHaveList.do )
- Sources codes -
[haveList.jsp]
Nothing special. There is list box
[loadData.js]
( function () {
var conn=null, addEvent=null, createXHR=null, loadNations = null, setAsyncLoad=null;
addEvent = (function(window){
if(window.addEventListener){
return function (element, eventName, callback, canCapture) {
element.addEventListener(eventName, callback, canCapture);
};
} else if(window.attachEvent){
return function (element, eventName, callback) {
element.attachEvent("on" + eventName, callback);
};
} else {
return function (element, eventName, callback) {
element["on" + eventName] = callback;
}
}
}(window));
createXHR = function () {
var xhrObj = null;
try{
xhrObj = new XMLHttpRequest();
} catch (exception){
try{
xhrObj = new ActiveXObject('Msxml2.XMLHTTP');
} catch (innerException){
xhrObj = new ActiveXObject("Microsoft.XMLHTTP");
}
}
return xhrObj;
};
loadAsync = function () {
var list = document.getElementById("list");
conn = createXHR();
conn.onreadystatechange = function () {
if(conn.readyState == 4){
if(conn.status == 200){
alert(conn.responseText); //--> Here it shows the html of haveList.jsp
}
}
};
conn.open('GET', 'requestListData.do');
conn.send();
};
addEvent(window, 'load', function () { loadAsync(); } , false);
} () );
[returnPage.java]
public class ReturnPage extends HttpServlet {
private static String page = "/haveList.jsp";
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
RequestDispatcher dispatcher = request.getRequestDispatcher(page);
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.addHeader("Cache-Control", "no-store");
response.setDateHeader("Expires", 1L);
dispatcher.forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
RequestDispatcher dispatcher = request.getRequestDispatcher(page);
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.addHeader("Cache-Control", "no-store");
response.setDateHeader("Expires", 1L);
dispatcher.forward(request, response);
}
}
[returnJsonData.java]
public class ReturnJsonData extends HttpServlet {
private String command = null;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
strUri = request.getRequestURI();
command = strUri.substring(request.getContextPath().length());
try {
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.addHeader("Cache-Control", "no-store");
response.setDateHeader("Expires", 1L);
response.setContentType("application/json; charset=UTF-8" );
response.getWriter().print( loadListData(request, command) );
} catch (Throwable e) {
System.out.println("Failed to load list");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
strUri = request.getRequestURI();
command = strUri.substring(request.getContextPath().length());
try {
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.addHeader("Cache-Control", "no-store");
response.setDateHeader("Expires", 1L);
response.setContentType("application/json; charset=UTF-8" );
response.getWriter().print( loadListData(request, command) );
} catch (Throwable e) {
System.out.println("Failed to load list");
}
}
private String loadListData(HttpServletRequest request, String command) throws Throwable
{
String codeList = null;
if("/requestListData.do".equals(command)){
codeList = codeDao.select(conn);
}
}
}
I solved it!! ^^
[Reason]
Because of my Filter.
[Detail]
Actually, haveList.jsp is a login page. And I have a filter that checks if request was logged in. If not, that filter redirects request to "haveList.jsp (login page)".
When ajax call to server ( requestListData.do ) was triggered, filter redirected request to login page because it was not logged in. Refer to following web.xml (Before).
<filter>
<filter-name>Checker</filter-name>
<filter-class>filter.Checker</filter-class>
<init-param>
<param-name>escape</param-name>
<param-value>/Test/,/Test/gate.jsp,/Test/openHaveList.do</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Checker</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>Checker</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
[Solution]
I registered ajax call to server as exception. (escape parameter) In my filter servlet, I do not redirect such exception to login page programmatically. Refer to following web.xml (After).
<filter>
<filter-name>Checker</filter-name>
<filter-class>filter.Checker</filter-class>
<init-param>
<param-name>escape</param-name>
<param-value>/Test/,/Test/gate.jsp,/Test/openHaveList.do,"/requestListData.do"</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Checker</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>Checker</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
After this, I got JSON data from server. ^^
Related
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).
I want to load an image from a servlet to a jsp file without storing it to any disk with help of jquery .It should be done Asynchronously . Below is my code
JSP.page ( Code of entire JSP page is not given ) . When the page is loaded GetCaptchaImage() function is called . This function will call doget method in the servlet Captcha. Image should be loaded in the result div. But nothing is been loaded . When I put an alert inside the javascript it shows data in encoded format .I have tried to encode the image in base64 format in servlet but still nothing comes to the browser. Even writing the response to printer object doesn't worked
data image link
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
function GetCaptchaImage ()
{
$.get("Captcha",function(data){
$('.result').html('<img src="data:image/bmp;base64,' + data + '" />');
});
}
</script>
</head>
<body onload="GetCaptchaImage()">
<div class="result" >
</div>
Servlet code :
#WebServlet("/Captcha")
public class Captcha extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* #see HttpServlet#HttpServlet()
*/
public Captcha() {
super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
gtcResult = captcha.GenerateCaptchaCustom(100) // Generates the image
InputStream in = new ByteArrayInputStream(gtcResult.getbmp());
BufferedImage bImageFromConvert = ImageIO.read(in);
response.setContentType("image/bmp");
OutputStream out = response.getOutputStream();
ImageIO.write(bImageFromConvert, "bmp", out);
out.flush();
out.close();
}
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
System.out.println("duration : "+ duration);
}catch(Exception e){
System.out.println("Image Failed : "+ e.getMessage());
}
//response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
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?
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()?
I am losing my mind trying to solve this problem over here. I have the following servlet deployed in Tomcat running on localhost:8080-:
#WebServlet(urlPatterns = { "/createcon" }, asyncSupported = true)
public class CreateCon extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* #see HttpServlet#HttpServlet()
*/
ConcurrentHashMap<String, AsyncContext> map;
public CreateCon() {
super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
public void init() {
map = new ConcurrentHashMap<>();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
AsyncContext context = request.startAsync(request,response);
context.setTimeout(10000);
if(!map.containsKey("Hello"))
map.put("Hello", context);
System.out.print("Inside GET");
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
AsyncContext context = map.get("Hello");
PrintWriter writer = context.getResponse().getWriter();
writer.write(request.getParameter("message"));
writer.flush();
System.out.print(request.getParameter("message"));
}
}
As you can see I am trying to store an AsyncContext that is created in Map. I code runs fine in Eclipse with Tomcat. As you can see above that I have added System.out.print to actually check whether the code is working properly or not. And it works exactly as expected.
But the problem is with the javascript below-:
function postMessage(){
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
alert(xmlhttp.responseText);
}
}
xmlhttp.open("POST", "/SampleTest/createcon", true);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var messageText = escape(document.getElementById("i1").value);
document.getElementById("i1").value = "";
xmlhttp.send("message="+messageText);
}
The onreadystatechange fires exactly when expected but the xmlhttp.responseText is always blank.
I know that there is something known as a same-origin policy. But I don't understand why that's a problem here ? I am running everything on localhost:8080.
Why is this still happening and how do I solve this ?
Okay solved it. Guess it was my own silly mistake. The startchat() method should be modified like-:
function startChat() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "/SampleTest/createcon", true);
xmlhttp.send();
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
alert(xmlhttp.responseText);
}
}
}
Since I am trying to find the result from the request made at startChat().