why we call post() method inside get() method in servlets?
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
Simply only because someone wants to have the same behavior disregarding the HTTP method whether it was POST or GET. So requesting resource with POST does the same as GET.
BUT: doing this - doing the same action - is quite propably wrong. Someone who does this might do it for convenience - for example wants to provide more means to access resource but does not fully understand the difference of GET vs. POST.
It is a matter of idempotency. Good explanation here.
In a nutshell GET should be used when GETting stuff and POSTing when you need to change stuff on the server side.
But what I have experienced some people use GET as long as there too much data for GET and then switch to POST without further thinking about the real difference.
Related
I have an ajax method on my servlet that could be running at the same time for the same user. Sorry if I use the wrong words to describe the problem but it's how I understand it so far (don't know much about threading).
Anyways here's the method
private void ajaxPartidas() throws ServletException, IOException {
//Variables necesarias
DataSource pool = (DataSource) session.get().getAttribute("pool");
Recibo registro = null;
int id = -1;
try{ id = Integer.parseInt(request.get().getParameter("id"));}catch(NumberFormatException e){}
if(id > 0){
registro = new Recibo(id);
if(!registro.obtener(pool))
registro = null;
registro.setPartidas(Partida.obtenerRegistros(pool, registro.getId()));
}
response.get().setContentType("application/json");
response.get().setHeader("Content-Type", "application/json; charset=utf-8");
response.get().getWriter().print((new Gson()).toJson(registro.getPartidas()));
}
This method is being called via ajax, it works fine the 1st time it gets called, but second time (on same id) and it returns a NullPointer on the getWriter() line. I've looked around and everyone seems to pinpoint the problem to threads. Now a little bit more of context would be that everytime the servlet enters in the
doPost(request, response)
I assign a threadlocal variable declared like so in the global vars
private static ThreadLocal<HttpServletResponse> response = new ThreadLocal<>();
and I assign it the response
Home.response.set(response);
in the doPost() method.
How would I go about making the getWriter() threadsafe?
Not sure why you're assigning the response to a class level ThreadLocal? Each new user generated request has a clean request and response object. getWriter and all methods on the servlet class are threadsafe as long as you follow the correct guidelines for using a Java Servlet. A general rule with Java Servlets is that as long as you don't use class level variables, you are thread-safe.
Instead of using a ThreadLocal, you need to pass the request and response objects as parameters to your ajaxPartidas method and then call it as you normally would. So your doPost method would look like this
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ajaxPartidas(request, response);
}
The concurrency issues are already handled by the Servlet class itself, you just need to write the business logic. See this answer in a similar thread for more details on using a Java Servlet with Ajax: https://stackoverflow.com/a/4113258/772385
Tomcat creates a new Request and Response for EVERY user request. So they are already threadsafe (unless you go in and create a new Thread). Besides, make sure you are passing "id" and is getting set properly. I think it's the "registro" object on the same line as getWriter() that's causing the NullPointerException.
I understand that the first call to getParameter will read the postdata content, if any.
Is there a way for me to limit how much postdata content would be processed into the RAM, or am I going to need to override the getParameter* methods for that to be accomplished?
I am not interested in making this a server-wide setting.
or am I going to need to override the getParameter methods for that to be accomplished?*
Yes.
For that you can use a homegrown HttpServletRequestWrapper which is injected by a Filter.
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(new MyPostDataLimitingRequest((HttpServletRequest) request), response);
}
I do not believe there is a way to limit through the existing getParameter(), which is a convenience method, without extending the servlet or adding a listener to break it down for you.
You can circumvent this by parsing the input stream within your servlet directly using getInputStream() or getReader(), but I believe this invalidates further calls to getParameter() for the rest of that request; you'll need to consume the rest of the input through your selected method.
It's not elegant, but it works.
Talking Java Servlets here... I'm working on creating my own "Per Request Context" and I was looking to tie the "Per Request Context" object to the Thread.currentThread().getId() value.
Instead of passing around this context object everywhere I was planning on checking the current threadid when a user calls a function that is Per Request based and automatically getting the Context object out of a hashtable for that threadId.
I would use the code this like..
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
MyFramework.EnterContext();
try {
// do stuff here that leads to other classes on the same thread
// Access current context via static MyFramework.getCurrentContext()
}
finally { MyFramework.ExitContext(); }
}
However I would like to protect my application automatically from any potential user that does not call ExitContext(). In C# there is an event handler on the thread object for onexit...(think I wrong on this) is there some way to detect or poll when a thread exits? I'm currently storing only the threadId (long).
Any ideas?
unfortunatelly, there is no such feature built in for threads in Java. Besides, thread id is only guaranteed to be unique at any one time, but may be reused eventually when the thread dies (from the docs). however, the servlet framework that you are using may be implementing such feature (just a speculation).
i would recommend you implement a servlet filter, and tell your users to include it in their web.xml. with this you can be sure the client code always gets correctly wraped in your thread context.
A ThreadLocal seems to fit your use perfectly. A ThreadLocal object can provide a way to store a variable per thread. The internal workings of this class are very much of what you describe, it uses a map to give thread-local variables.
Something like this should do the trick:
private static final ThreadLocal<UserContext> userContext = new ThreadLocal<UserContext>();
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
MyFramework.EnterContext();
try {
UserContext context = userContext.get();
//if you used the set method in this thread earlier
//a thread local context would be returned using get
}
finally { MyFramework.ExitContext(); }
}
As for your other problem, you can use an observer pattern and notify when the thread completes its task.
I want to write an HTML code inside Java, using a servlet. I read about the method doGet() and I wrote this simple example
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
PrintWriter out = response.getWriter( );
response.setContentType("text/html");
out.println("<H1>Hello from a Servlet</h2>");
But it doesn't give anything in the browser, can someone tell me what's wrong?
The standard PrintWriter which you get by calling response.getWriter(); doesn't automatically flush its buffers. It's a bug/feature.
Add out.flush() at the end of doGet().
Also note that PrintWriter.close() does not flush. It's a bug; PrintWriter/PrintStream are the only output classes which don't flush on close.
[EDIT] To make sure that no other problem confuses you, add a breakpoint in the method and run it in the debugger. You should also add the annotation #Override to make sure your method signature is correct.
It seems you don't actually override doGet. You missed the ServletException exception.
sorry but I do not have the actual code with me, but I will try to explain:
I have a servlet mapped to the following:
/admin/*
So, this goes to a servlet:
public class AdminController extends MainController {
public void doPost(HttpServletRequest request, HttpServletResponse response) {
// Do stuf here
}
}
Here is MainController:
public class MainController extends HttpServlet {
#Override
public void service(ServletRequest request, ServletResponse response) {
String requesturi = ((HttpServletRequest)request).getRequestURI();
reqlist = Arrays.asList(requesturi.substring(requesturi.indexOf(Util.rootPath) + Util.rootPath.length()).split("/"));
reqlist = reqlist.subList(1, reqlist.size());
doPost((HttpServletRequest)request, (HttpServletResponse)response);
}
So, the request is passed to AdminController, no problem, but then I reallized something:
The servlet is being called twice!. And this is causing me many errors..
Does anybody have a clue on this? It is because I used some kind of heritance?
Thank you for all!
Though it is old thread but my answer may help someone.
Today I faced the same issue. My particular servlet is working fine earlier and suddenly it has started calling doGet method twice. On investigation, I found that my chrome browser has html validator extension which is calling the servlet again with same request to do html validation.
After I disabling the extension, the problem got resolved.
The HttpServlet.service method gets called for all request types and what you are seeing is a HEAD request and then a GET or POST request. Instead of implementing service just implement doGet or doPost. What is commonly done is to just implement one of doPost or doGet and then call the other from the one you don't have an implementation for.
I solved same problem with simple way.
If you are developing local and access to your app with address http://127.0.0.1 which is loopback network, change address to http://localhost which is direct.
This problem won't happen if you actually run it on webhosting or server and access to it from outer network.
Had the same issue, and I tried anything mentioned above and on other posts, but the issue was only on local.
If nothing works for you too, try a deploy :)
I had the same issue. I had a servlet to handle a post request.
But after calling doPost it suddenly started to call doGet method.
So the doGet was called by a chrome plugin that I installed (FireBug Lite).
Problem solved after I deactivated that plugin.