Invoke only a method of a servlet class not the whole servlet - java

//Below is my servlet called HtmlTable. I am trying to implement shopping cart like functionality here. addingItems is another class that puts elements in a ArrayList. Whenever I add something from website I want AJAX request to just call the method jusAdding() not the processRequest method. so that when sufficient items are added to the ArrayList I can print it on the screen by calling aI.getItems() which will happen automatically when simply call the servlet. Is it possible?? If yes how should I write the URL in AJAX request.
public class HtmlTable extends HttpServlet {
addingItems aI = new addingItems();
public void jusAdding(HttpServletRequest request, HttpServletResponse response){
aI.addItemsInCart(request, response);
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
List<itemsCart> itemsInCart = aI.getItemsInCart();
try {
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet HtmlTable</title>");
out.println("</head>");
out.println("<body>");
//whatever content is in the itemsInCart will be displayed here in body tag
out.println("</body>");
out.println("</html>");
} finally {
out.close();
}
}
}
//forgive me if I am not clear. Let me know I'll update as per reader convenience.

You can't do that.
An HTTP request flowing through a Servlet will always go to the Servlet's service method. What you need is to use the service method as a controller, so it inspects the incoming request and calls jusAdding (or other methods) depending on the request's parameters.
Most likely, you will want to use an already-existing framework for doing that.
The following should give you more information, as well as some ideas how to go about doing so: How to use Servlets and Ajax?

None of your methods are going to be called by the container. You should start with the servlet specification (or at least the HttpServlet javadoc).
The container calls the service() method of your servlet, which in turn, for HttpServlet dispatches to the method corresponding to the request HTTP method: doGet(), doPost() etc. That's where you're supposed to hook your logic (overwrite one of those, or service() itself and put your code there).
In order to distinguish between a "full page request" and an "AJAX request", you need the client to include some discriminator in that call: some request parameter with distinct values, a different HTTP method or whatever. Once you have that, in your doGet() method for instance, you can check that discriminator and invoke either justAdd() or processRequest() according to the client request.

Related

Extract URL from HttpServletRequest

I am maintaining a Java servlet application and now have to extract the URL from the web service request to determine what action to take depending on what URL called the web service. I have found that it is something to do with HttpServletRequest which I have imported to the class. I have tried setting up the following inside the web service end point but it keeps telling me that the urlrequest is not initialised. What am I doing wrong?
HttpServletRequest urlrequest;
StringBuffer url = urlrequest.getRequestURL();
The HttpServletRequest you are using should be the input parameter HttpServletRequest of either doGet,doPut,doPost or doDelete.
Then Surely HttpServletRequest.getRequestURL will reconstruct the URL used by the client,excluding the query string parameters.
Your code is correct but it has to be accessed within the doPost(request, response), doGet(request, response) etc. methods of a class extending HttpServlet.
The reason for this is the when the service() method of HttpServlet is called, it populates the request and response objects for you given the client who prompted the request to your servlet.
You cannot define a variable in java and call a method on it without initializing it beforehand.
In the first line: HttpServletRequest urlrequest; you are just defining a variable. Since it is not initialized it is null and you cannot use it.
Remove this line and use the argument passed to the doGet (or doPost) method in your Servlet.
For example if your servlet is like this:
public class MyServlet extends HttpServlet {
...
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws Exception {
...
}
Instead of your code just add below line in the body of the doGet method:
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws Exception {
...
StringBuffer url = request.getRequestURL();
...
}
After this line you should be able to use the url variable.

Outputstream between threads

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.

How to implement state in command pattern

I am porting my Java servlet front controller from a large if-else if block to the command pattern and have created a command interface with an execute method. Currently, I am instantiating an instance of each command in the init() method of my servlet and storing them in a HashMap. I am wondering how I can run the necessary command.execute() within the context of a given request?
Do I add a setContext(HttpServletRequest request, HttpServletResponse response); method to the interface and call command.setContext(request, response) from my doGet()/doPost() methods before I execute or should I not be instantiating the commands in init() to begin with? instead, having a constructor that takes request and response as args?
Obviously, the aim of the command is to set various attributes for a given user/session and determine the correct JSP to forward to, which it can't really do without the context.
You should use:
command.execute(HttpServletRequest request, HttpServletResponse response);
All state can (and should) be recorded in the request. This is easy to do by storing attributes.
Sometimes you may need to use:
command.execute(this, HttpServletRequest request, HttpServletResponse response);
but probably only if your commands are enum rather than real objects.

servlet which can call a method and pass the value extracted from the web request

i have a question on how a servlet call a method and pass the value extracted from the web request. A scenario in which a web request is processed in a web request, i need to call a method and pass in the values extracted from the web request. When the method returns a value, send the value in the web response. thanks
If I understand you right you need something like this:
public class MyNewServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String param = request.getParameter("paramname");
String result = MyBusinessClass.myBusinessMethod(param);
response.getWriter().append("The answer is: " + result);
}
}
When request comes from browser, it will first read web.xml and call service method of appropriate servlet. Then service method decide to call doPost or doGet method on the basis of request. Once you get parameter , you need to create object of requestDispatcher and call forward method which will send your response.

Is it possible to change the httpservletrequest object

Is it possible to change the Servlet request object while forwarding the request from one servlet to another? or a work around for achieving this?
I have 2 servlet's, Servlet1 and Servlet2 like for e.g. -
public class Servlet1 extends HttpServlet {
doPost(HttpServletRequest rq, HttpServletResponse rs) {
// do something meaningful, call other different web-apps/servlets
InputStream is1 = rq.getInputStream();
RequestDispatcher rd = getServletContext().getRequestDispatcher("/Servlet2");
rd.forward(rq, rs);
}
}
If I print the is1 it is something like -
-----Part2_324<?xml version="1.0" encoding="utf-8"?><Head><Body><Text>This is the first File</Text></Body></Head>-------Part2_65623
I dont care about this o/p, when later the request is to be forwarded to the Servlet2.
I have an xml file file2.xml, contents are -
<?xml version="1.0" encoding="utf-8"?><Head><Body><Top>Start</Top><Middle>Process</Middle><Bottom>End</Bottom></Body></Head>
I would like this to be as the request content for the Servlet2, as it cannot process the contents of is1, it is meant to be processing content of file2.xml.
There are pretty much no Attributes/Parameters set.
Is it possible to achieve this? I hope, the question is clear.
Thank you
The servlet spec forbids the substitution of one request for another when forwarding.
However, it does permit the forwarding of an HttpServletRequestWrapper, where the wrapper is wrapping the original request. So try and implement your logic as a subclass of HttpServletRequestWrapper, wrapping the original request, and overriding the various methods of HttpServletRequest as appropriate.

Categories