Forward A servlet request to a .html file in java? - java

Basically I have servlet named forward. When a request is made to it, it forwards the request to a .html file like this:
#WebServlet("/forward")
public class forward extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/videos/forward.html").forward(request, response);
return;
}
}
The problem is that when I test this on eclipse when a request is made to this servlet, it responds with the link as localhost/videos/forward.html
But then when I deployed it with name com.war Now when a request is made to it, it responds with localhost/com/videos/forward.html
How can I make the requestDispatcher to respond with localhost/videos/forward.html and not as localhost/com/videos/forward.html

No you cannot. Forwarding is a request made to the servlet container to pass control to another servlet in same servlet context. A JSP page in indeed implemented as a servlet, but a HTML is just a ressource, so you cannot forward to it.
But you can redirect to it. A redirection works by sending a special response telling the browser that it should go to that other URL. As it works at browser level, you can redirect to a HTML page or even to a completely different site.
You can use the sendRedirect method from HttpServletResponse to initiate a redirection from a servlet:
#WebServlet("/forward")
public class forward extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendRedirect("/videos/forward.html");
return;
}
}

Just write
response.sendRedirect(pagename.html)

Yes, u can.
use:
RequestDispatcher r = req.getRequestDispatcher(String arg);

Related

How to make jersey and #webservlet working together

How to make jersey and #webservlet working together ?
jersey ResourceConfig:
#ApplicationPath("/*")
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
register(Greetings.class);
}
}
jersey Resource registered in resourceConfig:
#Path("/login")
public class Greetings {
#GET
public Response getHelloGreeting(#Context HttpServletRequest httpRequest) {
System.out.println("In the Greetings resource");
String url= "http://"+httpRequest.getServerName()+":"+httpRequest.getServerPort()+httpRequest.getContextPath();
String newURL = url+"/login.jsp";
System.out.println(newURL);
return Response.seeOther(URI.create(newURL)).build();
}
}
web servlet
#WebServlet(name = "LoginServlet", urlPatterns = { "/hello" })
public class LoginServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext servletContext = getServletContext();
System.out.println("inside login servlet");
request.getRequestDispatcher("/login.jsp").forward(request, response);
System.out.println("request forwarded");
}
//other functions not important so deleted
}
Case 1: on accessing this
http://localhost:8088/ResponseFilterweb/login
console logs:
In the Greetings resource
http://localhost:8088/ResponseFilterweb/login.jsp (no ui comes)
on accessing this
http://localhost:8088/ResponseFilterweb/hello
(nothing happens 404 error)
Case 2: Changing application config resource path:
#ApplicationPath("/auth")
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
register(Greetings.class);
}
}
on accessing this
http://localhost:8088/ResponseFilterweb/auth/login
In the Greetings resource
http://localhost:8088/ResponseFilterweb/login.jsp (Ui comes)
on accessing this
http://localhost:8088/ResponseFilterweb/hello
inside login servlet (Ui comes)
userid is
Encoded string
request forwarded
doubts:
don't know why login.jsp is blocked in the first case:
why http://localhost:8088/ResponseFilterweb/login not showing any ui .. i think it should come ?
why http://localhost:8088/ResponseFilterweb/hello not showing any ui ?
If you were using web.xml, this or this would be your solution, but since you're not, this might be your only option. The problem is that when you use /* as the servlet mapping for Jersey, it hogs up all the requests. So the request to /hello would go to Jersey and not the LoginServlet. What those solutions I linked to do is cause Jersey to forward the request if it can't find it within the Jersey application. The other solution is to just change the servlet mapping to something like /api/* (which is pretty common), then you would just prefix your API requests with /api.
Using asterisk (*) won't work using #ApplicationPath
If you use /*, then you're making it too greedy and saying it should match everything all the time, and the default servlet will never be invoked
Use #ApplicationPath("/") instead
If you use /, then you're replacing the container's default servlet

How to process / URL while having default processing for /js,/css,

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");
}

Is it possible to redirect to the same JSP page from a Servlet?

A JSP page named Test.jsp is mapped to the following Servlet.
#WebServlet(name = "TestServlet", urlPatterns = {"/TestServlet"})
public final class TestServlet extends HttpServlet
{
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
//request.getRequestDispatcher("/WEB-INF/admin_side/Test.jsp").forward(request, response);
response.sendRedirect("TestServlet");
}
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
#Override
public String getServletInfo() {
return "Short description";
}
}
This Servlet is mapped to a JSP page Test.jsp. The doGet() method is invoked, when a URL like http://localhost:8080/Assignment/TestServlet is entered in the address bar.
The request can be forwarded to the given URL as commented out. Is it possible to redirect to the same JSP page, Test.jsp?
If an attempt is made to do so, Google Chrome complains,
This webpage has a redirect loop
It can however, redirect to other pages under WEB-INF/admin_side.
The POST-REDIRECT-GET pattern works like so: a client sends a POST request, your server handles it and responds with a redirect, ie. a response with a 302 status code and Location header to the appropriate URI. The client makes a GET request to that URI.
Currently, your server is redirecting on both GET and POSTS requests. What's worse is that your GET is redirecting to the same URI that it is handling, creating the redirect loop you are seeing.
Change your Servlet implementation so that the POST sends a redirect, but the GET actually serves up a normal 200 response with HTML, AJAX, etc.

how to prevent servlet from being invoked directly through browser

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.

Calling service() of servlet from another servlet

I have a url-mapping in my web.xml such that requests for a specific url x.pt gets mapped to a Servlet say Servlet1. In the service() of this servlet I check if the request has some specific parameter.
If so, the call is delegated to another servlet Servlet2 by instantiating it and calling its service method.
public void service(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
// if the call is for some special events (request has some specific parameter)
if (req.getParameter(conditionCheck()) {
doPost(req, res);
} else {
// Report parsing
}
}
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
try {
// instantiate Servlet2 object
servlet2.init(this.getServletConfig());
servlet2.service(req, res);
servlet2.destroy();
} catch (Exception e) {
LOG.error("Unable to execute event", e);
}
}
The browser returns some JSON text when the request is for special events( i.e. to Servlet2)
Do let me know if I need to do something extra for getting response of Servlet2 to the brwoser.
Thanks in advance!
You can forward your request using RequestDispacher:
RequestDispatcher rd = getServletContext().getRequestDispatcher(destination);
rd.forward(request, response);
As Kris says, I'd expect a RequestDispatcher to work, but I'm always uncomfortable when I see a servlet being called directly like this. Do you have the opportunity to move the logic that is provided by servlet2 into a separate object that both servlet1 and servlet2 can call upon? If you can, I think it'll give you a better, more easily testable solution.

Categories