In my servlet:
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
new Action();
}
In my Action class:
Action(){
System.out.println("--> " + this.getClass().getResource("/").toString());
}
I have on result, this location:
--> file:/C:/Users/saad/Desktop/apache-tomcat-7.0.37/wtpwebapps/Serveur/WEB-INF/classes/
But i would like to get access to the root of my webApp like this:
file:/C:/Users/saad/Desktop/apache-tomcat-7.0.37/wtpwebapps/Serveur/
I insist that the Action class does not inherit from the HttpServlet, so i can't use ServletContext.getResource("") .
How can i do this ?
You can get the actual file system path of a web resource by using ServletContext.getRealPath() method.
ServletContext ctx = request.getServletContext();
String path = ctx.getRealPath("/");
And modify your Action to take either the request or the servlet context as a parameter:
public Action(ServletContext ctx) {
System.out.println("--> " + ctx.getRealPath("/"));
}
Related
I am trying to write the JUnit test case for the code:
In SearchController class
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
List<AlbumSimplified> items = spotifyService.searchAlbum(searchName);
request.setAttribute("items", items);
request.getRequestDispatcher("searchResult.jsp").forward(request, response);
}
as
public void SearchControllerTesting() throws ServletException, IOException {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
//mocked myalbums
when(searchServiceMock.searchAlbum(anyString())).thenReturn(myalbums); when(request.getRequestDispatcher(anyString())).thenReturn(request.getRequestDispatcher("searchResult.jsp"));
searchController.doGet(request, response);
}
The error I am facing is:
java.lang.NullPointerException: Cannot invoke "jakarta.servlet.RequestDispatcher.forward(jakarta.servlet.ServletRequest, jakarta.servlet.ServletResponse)" because the return value of "jakarta.servlet.http.HttpServletRequest.getRequestDispatcher(String)" is null
I believe that it is due to the fact that the uri is not identified for the request and so, it is not able to find the "searchResult.jsp" located at "/app/src/main/webapp/searchResult.jsp" where app is the root of the project directory.
Hence I tried to set the
when(request.getRequestedURI()).thenReturn("app/search"), which is the URL of the request in the browser for non-testing usage.
However, I am not able to move ahead and solve the issue.
I want the items in the request to go to the searchResult.jsp, and return me a response of type "text/html".
Thanks.
I have HttpServlet class called, let's call is Test. I can output anything from this class using HttpServletResponse object into my html page. Now, I have another a plain java class, let's call it Home, and in this class I need to out put something into the html page. Unfortunately, it doe snot work even I have tried to inherit HttpServlet from Home class and use HttpServletResponse object to out put.
Is there a way to redirect the output from the Home class to Test class ?
Here's the method doGetof my Test class, it create an object of home and call the method connectToHom() for authentication.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String tst = "username"
tst = new Home();
tst.connectToHome(tst);
}
Here's the method connectToHome() of the class Home:
public void connectToHome(String tst){
-> Try to login using tst,
connect = Connection.open(tst);
if(connect.getMessage()!=null){
System.out.println("-- Error: " + connect.getMessage());
return null;
}
}
The above code works but it prints out on the console instead on the html page.
Thanks in advance!
you need to send an OutputStream ref. to Home class:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String tst = "username"
tst = new Home();
tst.connectToHome(tst, response.getOutputStream());
}
public void connectToHome(String tst, OutputStream out){
-> Try to login using tst,
connect = Connection.open(tst);
if(connect.getMessage()!=null){
out.print("-- Error: " + connect.getMessage() + "\n");
out.flush();
return null;
}
}
For a WebApp, I need to serve all .js, .css and all images from corresponding folders in my web app development tree ./js, ./css, ... through a default handling.
So any URL like
http://www.example.com/js/x.js
should be served straight from the static files in the war.
The main servlet should deal with all requests that are not for the above.
I need to be able to process requests like
http://www.example.com/PROJ/ELEM/WHATEVER
with the same unique main servlet.
So I thought I'd do this in the web.xml:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/css/*,/js/*,/WEB-INF/*</url-pattern>
</servlet-mapping>
and map the main servlet like this to make some JSTL mods in a JSP file:
#WebServlet(urlPatterns="/*")
public class Main extends HttpServlet {
protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
request.setAttribute("test", "ok");
request.getRequestDispatcher("/WEB-INF/index.jsp")
.forward(request, response);
}
}
When I do this I end up in a recursive loop.
Is there a way to achieve this?
Here is the explanation with same problem.
http://www.kuligowski.pl/java/rest-style-urls-and-url-mapping-for-static-content-apache-tomcat,5
This is what already happens. There is a 'default servlet' that handles any request that isn't specifically mapped to an installed servlet.
A simple variation on Rahul Jain's answer. You could do what spring MVC does for static resources : DispatcherServlet is a catch all, and it is configured to delegate to default servlet for a number or url. This may be interesting for a catch all servlet because it is often designed as a front controller that delegates actual serving to other controllers (be them servlets or not).
You can simply give the prefixes of urls that should serve static resources in a comma separated string in a context param of name static_path_prefixes and put that in your servlet :
String[] staticPathPrefixes;
RequestDispatcher defaultDispatcher;
#Override
protected void service(HttpServletRequest hsr, HttpServletResponse hsr1) throws ServletException, IOException {
String path = hsr.getServletPath();
for (String url: staticPathPrefixes) {
if (path.startsWith(url)) {
defaultDispatcher.forward(hsr, hsr1);
return;
}
}
super.service(hsr, hsr1);
}
#Override
public void init() throws ServletException {
String urls = getServletConfig().getInitParameter("static_path_prefixes");
staticPathPrefixes = urls.split(" *, *");
defaultDispatcher = getServletConfig().getServletContext().
getNamedDispatcher("default");
}
I was working on a web project using java servlet and jsp pages. In one of the servlet we have RequestDispatcher method and which is calling another servlet.
#WebServlet("/Demo")
public class DemoServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.sendRedirect("testing"); //calling other servlet
}
}
#WebServlet("/testing")
public class TestingServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("Hello World");
}
}
So, now I wanted to prevent contextRoot/testing from being invoked directly from the browser but instead only let it invoked from the other servlet(Demo)
Please suggest me if there is any way to do that.
Couple of techniques exist:
Look at writing a HTTP Request Filter. You can then inspect the incoming request and the url and reject it if the pattern matches the servlet paths that you do not want to be invoked directly.
Another mechanism is to use the security constraints in your web.xml to allow access to various paths in your application only to authorized users/roles. Look at <security-constraint> tag in web.xml
Answer given by "Romin" is correct. You have to use Filters for this. what you can do is, you can set a new session variable whenever "/Demo" url is accessed and in the filter check for the condition that session exists, if it exists allow the url or else throw error. You could do something similar like this. In "Demo" servlet
#WebServlet("/Demo")
public class DemoServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
HttpSession session = request.getSession() //get new session
res.sendRedirect("testing"); //calling other servlet
}
}
In Filter class add the below code
#WebFilter("/login")
public class MyFilter implements Filter{
public void init(FilterConfig arg0) throws ServletException {}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpRequest request = (HttpRequest) req;
HttpResponse respone = (HttpResponse) res;
HttpSession session = request.getSession(false) //get the existing session object
if(null != session) {
chain.doFilter(req, resp);
} else {
"redirect to some error page or home page"
}
}
public void destroy() {}
}
One approach is to check the caller's ip using ServletRequest.getRemoteAddr() and rejects it if it's not called locally
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
if(!req.getRemoteAddr().equals("127.0.0.1")) { // reject }
}
However this method wouldn't work legitimate caller (eg: proxy) is also using the same ip.
I need to create add servlets at runtime. When I run the following code.
protected void processRequest(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException
{
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
out.println("<html>");
out.println("<head>");
out.println("<title> URI out</title>");
out.println("</head>");
out.println("<body>");
Integer generatedKey = Math.abs(randomiser.nextInt());
out.print(generatedKey);
createServlet(Integer.toString(generatedKey),request.getServletContext());
} finally {
out.println("</body>");
out.println("</html>");
out.close();
}
}
private void createServlet(String generatedKey, ServletContext servletContext) {
String servletMapping = "/"+generatedKey;
ServletRegistration sr = servletContext.addServlet(generatedKey, "com.path.lbs.servlets.testDynamic");
sr.setInitParameter("keyname", generatedKey);
sr.addMapping(servletMapping);
}
I get the following error.
java.lang.IllegalStateException:
PWC1422: Unable to configure mapping
for servlet 1114600676 of servlet
context /123-LBS, because this servlet
context has already been initialized
Is it impossible to add new servlets at runtime i.e. after the Servlet Context is initialised or am I doing something wrong?
Is it impossible to add new servlets at runtime i.e. after the Servlet Context is initialised?
That's correct. You need to do it in ServletContextListener#contextInitialized().
#WebListener
public class Config implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent event) {
// Do it here.
}
#Override
public void contextDestroyed(ServletContextEvent event) {
// ...
}
}
However, for your particular functional requirement, a single controller servlet in combination with command pattern is much better suited. You could then add commands (actions) during runtime and intercept on it based on the request URI. See also my answer on Design Patterns web based applications for a kickoff.