I have implemented a HttpServlet that uses java.util.logging for leaving Log.
Now I want that the Servlet leaves the Log inside a txt file.
I know the FileHandlers implements this functionality.
Doubts:
Where I have to put the code that adds the FileHanlder to the Logger? by "where", I mean in which part of the code. I think that in the service() method is not correct at all.
#Override
protected void service(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
// HERE???
}
I want that the FileHandler is instanced only one time , so I have no locks problem with the txt file. How can I do that? Do you have any samples of code/recommendations?
Please forgive my bad explanation, but I am lost, and very noob in Java.
Related
I'm super new to java web application development. Working on basic Todos app. So far app is working fine. I wish to add dynamic url routes like updateTodos, deleteTodos to existing path.
Expected behavior as shown below
/todos
*render todos list*
/todos/update
*render updateTodos.jsp*
/todos/delete
*render deleteTodos.jsp*
Below is my code
#WebServlet(urlPatterns = "/todos")
public class UserTodos extends HttpServlet {
private TodoService todoService = new TodoService();
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
if(request.isRequestedSessionIdValid()){
request.setAttribute("userName", request.getParameter("userName"));
request.setAttribute("allTodos", todoService.retrieveTodos());
request.getRequestDispatcher("WEB-INF/views/todos.jsp").forward(request, response);
}else{
response.sendRedirect("/login");
}
}
}
My understanding is so far that the annotation #WebServlet triggers the class file based on route defined. Can I achieve the above with a single class file?
Something like being done in JS web-framework Express-JS
If I sum-up my whole query is - Is it possible to multiple doGet and doPost methods in a single class file which will be executed based on user's URL accessed?
Update
I was able to achieve this, not sure whether this is correct implementation or not :/
This question already has answers here:
How do servlets work? Instantiation, sessions, shared variables and multithreading
(8 answers)
Passing an object from JSP page back to Servlet
(3 answers)
How can I store state for an individual browser tab/window?
(2 answers)
Closed 5 years ago.
This is the sample code, illustrating the usage of instance variable and request attribute:
#WebServlet(name = "Upload", urlPatterns = {"/upload"})
#MultipartConfig()
public class Upload extends HttpServlet {
private String txt;
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try{
String txt2 = (String) request.getAttribute("txt2");
//txt and txt2 variables are available for processing.
..........
} finally {
txt = null;//Prepare variable for next request.
}
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
.....
request.setAttribute("txt2", someValue);
//vs
txt = someValue;
processRequest(request, response);
}
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
.....
processRequest(request, response);
}
}
Now I know that instance variables should be never declared in servlets, because the same servlet is shared between concurent requests. But what about request attributes? Is it safe to use them?
Not sure what you mean by initializing variables. On a servlet you mean or where?
Depending on what you need to do, maybe there are APIs involved in which you don't have control about the contracts (since they are not your APIs).
For example, when requesting is being processed by a filter chain. Maybe one filter is interested on data being set by a filter executed previously in the chain. You don't have means to pass data on the filter chain contract. Request attribute might be an option. Playing with ThreadLocal might be another, but it has performance implications and is not always suitable.
Another example, maybe you forward one request from a servlet to another. Again, you will not have an option to play with whatever member variable you define.
Also, if you were thinking on adding member variables on a servlet, remember Servlets are not thread-safe. What would you do? synchronize request processing, only one request being processed per servlet?
Your servlet is going to serve hundreds on concurrent request each one of them will use same shared instance of the servlet, therefore using private instance variable will lead to inconsistent behavior. Unless you synchronize access to it, which will lead to greater contention on access to this private field, therefore slowing down response time, producing bottleneck.
While storing attribute within binded to single request will allow you to avoid such problem, moreover it was designed to overcome issues similar to yours.
This question already has answers here:
HttpServletResponse sendRedirect permanent
(2 answers)
Closed 7 years ago.
I am making a servlet for attendance. So in the doGet() method all the front end is displayed and if any error is generated ; i.e., something is left blank then the doPost() method should call the doGet() again for completing the blank spaces.
How can I call doGet() method from the same servlet's doPost()?
If I take your question literally (i.e. invoke doGet() from doPost()), you can just invoke the doGet() method... it's a standard method like any other.
Here's a tip: When the doPost() and doGet() methods share a common set of logic, it's a good practice to isolate that logic into a separate (private) method that is to be invoked by all relevant do***() methods. For example:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// GET-based logic
processCommonLogic();
// Other GET-based logic
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// POST-based logic
processCommonLogic();
// Other POST-based logic
}
private void processCommonLogic() /* throws ServletException and/or IOException if needed */ {
// Common logic
}
You can use this pattern to create a processError() method that can be invoked wherever you need it.
However, if the scope your question goes beyond invoking doGet() from doPost(), I suggest you have a look at the references pointed by Alain O'Dea.
You can do that, it's a simple
this.doGet(req, resp);
return;
However, it's not a best practice. Generally better to implement view logic as a JSP, and dispatch to it from the post logic...
this. getServletConfig().getRequestDispatcher("my_view.jsp")
.forward(req,resp);;
return;
Or use include(), or an MVC framework like Struts...
I am quite new to JSP, servlets, etc.
I am making a website for learning purposes. I would like it to have a classic layout - menu on the left, and content in central part. I came across problem: I want to make "dynamic menu". It would load some data from database (countries). I can do it on single page by creating a servlet that returns those countries for me.
#WebServlet("/countries")
public class LeagueCountriesServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
processRequest(req,resp);
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
processRequest(req,resp);
}
void processRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
LeaguesDAO dao =
(LeaguesDAO)req.getServletContext().getAttribute("leaguesDAO");
List<String> list = dao.getAllCountries();
req.setAttribute("countrylist", list);
RequestDispatcher view = req.getRequestDispatcher("menulist.jsp");
view.forward(req, resp);
}
}
However, in fact it works only if I access "/countries". I would like to make it appear on many pages.
I tried to solve it with including it in other JSPs
<jsp:include page="/countries" />
But this causes that website is being "cut" after that included part.
What is the proper way to handle "layouts" like that?
I could generate response for this menu in every servlet, but it doesn't sound like a proper method.
I believe that i should divide template into two parts: pre-content holding header, menu, etc, and post-content holding footer etc, and include them in .jsp's used to display content-data coming from servlets. But how to avoid problems with dynamically generated menus?
<jsp:include page="before-content.jsp" />
(here some code to display specified web page)
<jsp:include page="after-content.jsp" />
Thanks for help!
You should change path in #WebServlet("/countries") not in JSPs, web server (Tomcat/Jetty/etc) are dispatches http requests looking into servlet mapping. Afterwards your servlet points which jsp should be used to generate desired html page.
Have a look at Apache Tiles, implementing the Composite View Pattern or Sitemesh, which uses the Decorator Pattern.
In Tiles you can define some templates for the header, footer and menu part and reuse them for every page.
I find it extremely useful when doing Django/Python web development to fully inspect a HTTP request like this:
logger = logging.getLogger(__name__)
def index(request):
logger.info(request)
Is there something similar for a Java Servlet?
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// debugInfo should print something similar to what you get in DJANGO
debugInfo(request);
}
Since I got no answers, I wrote a little helper class to help me with this issue. Hope someone else finds it interesting and useful.