web.xml URL pattern - java

Can anyone give me the information regarding rules in setting URL pattern and if I am using / as my index page and also I need to use request.getRequestDispatcher("/html/file.html").forward(request,response).
File file.html is in the html folder which is under war folder, html folder is in the same folder of WEB-INF
Can any one give me suggestion?
Thank you

You can define a servlet in your web.xml as below and then use request.getRequestDispatcher("file").forward(request,response), essentially what will happen is that you would be dispatching your request to a servlet whose mapping is /file and that servlet would point you to your resource /html/file.html. Please note that even though the element name is jsp-file but you can point a HTML from it.
<servlet>
<servlet-name>FileServlet</servlet-name>
<jsp-file>/html/file.html</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>FileServlet</servlet-name>
<url-pattern>/file</url-pattern>
</servlet-mapping>
As an add-on - coming to how URL patterns matches the serlvet mapping present in web.xml file, below are servlet mapping rules in web.xml (sources of this are - Servlet specs and #BalusC answer):
1. Path mapping:
If you want to create a path mapping then start the mapping with / and end it will /*. For example:
<servlet-mapping>
<servlet-name>FileServlet</servlet-name>
<url-pattern>/foo/bar/*</url-pattern> <!-- http://localhost:7001/MyTestingApp/foo/bar/index.html would map this servlet -->
</servlet-mapping>
2. Extension mapping:
If you want to create an extension mapping then have servlet mapping *.. For example:
<servlet-mapping>
<servlet-name>FileServlet</servlet-name>
<url-pattern>*.html</url-pattern> <!-- http://localhost:7001/MyTestingApp/index.html would map this servlet. Also, please note that this servlet mapping would also be selected even if the request is `http://localhost:7001/MyTestingApp/foo/index.html` unless you have another servlet mapping as `/foo/*`. -->
</servlet-mapping>
3. Default servlet mapping:
Suppose you want to define that if a mapping doesn't match any of the servelt mapping then it should be mapped to the default servlet then have servlet mapping as /. For example:
<servlet-mapping>
<servlet-name>FileServlet</servlet-name>
<url-pattern>/</url-pattern> <!-- Suppose you have mapping defined as in above 2 example as well, and request comes for `http://localhost:7001/MyTestingApp/catalog/index.jsp` then it would mapped with servlet -->
</servlet-mapping>
4. Exact match mapping:
Suppose you want to define exact match mapping then do not use any wild card character or something, and define the exact match, like /catalog. For example:
<servlet-mapping>
<servlet-name>FileServlet</servlet-name>
<url-pattern>/catalog</url-pattern> <!-- Only requests with http://localhost:7001/MyTestingApp/catalog will match this servlet -->
</servlet-mapping>
5. Application context root mapping:
The empty string "" is a special URL pattern that exactly maps to the
application's context root. i.e., requests of the form http://localhost:7001/MyTestingApp/.
<servlet-mapping>
<servlet-name>FileServlet</servlet-name>
<url-pattern></url-pattern> <!-- Only requests with http://localhost:7001/MyTestingApp/ will match this servlet Please note that if request is http://localhost:7001/MyTestingApp/abc then it will not match this mapping -->
</servlet-mapping>
6. Match all mapping:
If you want to match all requests to one mapping or override all other servlet mapping then create a mapping as /*.
<servlet-mapping>
<servlet-name>FileServlet</servlet-name>
<url-pattern>/*</url-pattern> <!-- This will override all mappings including the default servlet mapping -->
</servlet-mapping>
Below is the summary diagram from JMS specification:

Related

Why I get null when retrieving servlet's init parameter from JSP?

I have DD (web.xml file) with very simple code:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>TestProject</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>test</servlet-name>
<jsp-file>/result.jsp</jsp-file>
<init-param>
<param-name>email</param-name>
<param-value>example#gmail.com</param-value>
</init-param>
</servlet>
<context-param>
<param-name>name</param-name>
<param-value>Max</param-value>
</context-param>
</web-app>
Notice I have two parameters (one in application, other in configuration scope). When I try to get them inside result.jsp with:
<html><body>
Name is: <%=application.getInitParameter("name") %>
<br>
Email is: <%=config.getInitParameter("email") %>
</body></html>
, I get following output:
Name is: Max
Email is: null
My question is simple: how did I get NULL for "email" parameter? Shouldn't my JSP file "see" how I configured it and return "example#gmail.com"?
Is that your entire web.xml file? And by any chance are you accessing the JSP directly in the browser? Like:
http://localhost:8080/<yourAppContext>/result.jsp
If that is the case, then you will get this response:
Name is: Max
Email is: null
It is not wrong. It is correct.
The reason you get this result is that you are not accessing the JSP through the configuration you defined in web.xml, you are just accessing the JSP directly, which behind the scene has a different implicit configuration, and it's not the one you think you are configuring.
If you want this response:
Name is: Max
Email is: example#gmail.com
Then you need to add a servlet mapping. The complete configuration is:
<servlet>
<servlet-name>test</servlet-name>
<jsp-file>/result.jsp</jsp-file>
<init-param>
<param-name>email</param-name>
<param-value>example#gmail.com</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
and you need to access this URL, not the JSP path, with:
http://localhost:8080/<yourAppContext>/test
You might want to also read these:
Url Mapping For Jsp
Servlet JSP web.xml
To further drive the point home, it's important to mention that you need a mapping for one of your servlets to be useful. If you just define a servlet in web.xml, it just sits there. You need to tell the server how to use it, and for that you use the <servlet-mapping>. It's saying to the server that for a request on a path, some specific servlet needs to be called to handle the request.
You can create this mapping to point to a servlet class using <servlet-class> or to a JSP using <jsp-file>. They are basically the same thing, since a JSP eventually becomes a servlet class.
What I think is confusing you (based on the comment below) is that for JSP files you already have some implicit mapping created by the server, as described here.
When you access the JSP directly, with
http://localhost:8080/<yourAppContext>/result.jsp
you are using the implicit server mapping which contains no special configuration attached (like the email you want to send to it).
When you access the JSP with
http://localhost:8080/<yourAppContext>/test
you are accessing your mapping. And this you can configure however you want, and send it whatever parameters you want, and your JSP will now be able to read them.

Adding default servlet and forwarding to an HTML creates stackoverflowerror

I am using Jetty. My default servlet is making a simple forward to an HTML file in my WEB-INF folder that is causing a java.lang.StackOverFlowError error. The error is fixed if I rename the file I am forwarding from a .html to .jsp
DefaultServlet.java
public class DefaultServlet extends HttpServlet{
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{
req.getRequestDispatcher("WEB-INF/home.html").forward(req, resp);
}
}
web.xml
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>Default</servlet-name>
<servlet-class>DefaultServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
My guess is that instead of inserting the html content in the response body, the forward is sending the browser a redirect to /WEB-INF/home.html. This again calls the DefaultServlet and gets into an infinity loop. How can I prevent this?
Thanks.
The "default servlet", which is mapped on a special URL pattern of /, is a very special servlet which is invoked when there's a request which does not match any of the servlets mapped on a more specific URL pattern such as *.jsp, /foo/*, etc.
When you forward to home.html, for which apparently no one servlet is registered, then the default servlet is invoked once again. However, the default servlet is ignorantly forwarding to the very same HTML file once again instead of actually serving the requested HTML file. It'll on the forward still find no one servlet matching the forward URL and it'll still invoke the default servlet once again. And again. Etc. When this is performed so many times that the stack cannot keep track anymore of all those in sequence invoked doGet() methods (usually around 1000), then you'll get a StackOverflowError.
That it works with a JSP file has actually a very simple reason: there's already a JspServlet registered on an URL pattern of *.jsp. So the badly designed default servlet isn't invoked.
Your default servlet should instead be obtaining the HTML file's contents via ServletContext#getResourceAsStream() and write it to the HttpServletResponse#getOutputStream().
However, it's also quite possible that you completely misunderstood the whole meaning of "default servlet" and/or the special meaning of the URL pattern / and actually merely want a servlet acting as home page. In that case, you should be mapping the servlet on a more specific URL pattern (and please rename the currently obviously quite confusing class name DefaultServlet to something else):
<servlet>
<servlet-name>home</servlet-name>
<servlet-class>com.example.HomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>home</servlet-name>
<url-pattern>/home</url-pattern>
</servlet-mapping>
And then register exactly that URL as welcome file:
<welcome-file-list>
<welcome-file>home</welcome-file>
</welcome-file-list>
You need kind of exclude urls ends with "html".
See for example this link explaining similar problem solution Can I exclude some concrete urls from <url-pattern> inside <filter-mapping>?

Relay servlet (servlet calls another servlet)

Hello i have a question about servlet calling another servlet
I have a main servlet called Relay which is going to be responsible to control the other servlets
the user will click on and will be forwarded to Relay servlet
<li>Check the available animals </li>
inside Relay servlet will get the value of the parameter to determine which servlet is going to run
String selectAnimal = request.getParameter("selectAnimal");
if (selectAnimal.equals("SelectAnimalServlet")){
getServletContext().getNamedDispatcher("/SelectAnimalServlet")
.forward(request, response);
//for testing
System.out.println("Request forwarded to " + selectAnimal + " servlet");
}
SelectAnimalServlet code:
try
{
HttpSession session = request.getSession(true);
session.getAttribute("currentSessionUser");
List<AnimalSelectBean> beans = DAO.getAnimalList();
request.setAttribute("beans", beans);
request.getRequestDispatcher("CheckAnimal.jsp").forward(request, response);
}
Now when i run that it's not working for some reason, if i change the link to SelectAnimalServlet directly the code works any idea how to solve this ?
Edit:
Here is my web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:javaee="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>content.LoginServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>UpdateAnimalServlet</servlet-name>
<servlet-class>content.UpdateAnimalServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>SelectAnimalServlet</servlet-name>
<servlet-class>content.SelectAnimalServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>Relay</servlet-name>
<servlet-class>content.Relay</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SelectAnimalServlet</servlet-name>
<url-pattern>/SelectAnimalServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>UpdateAnimalServlet</servlet-name>
<url-pattern>/UpdateAnimalServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/LoginServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Relay</servlet-name>
<url-pattern>/Relay</url-pattern>
</servlet-mapping>
</web-app>
also I changed:
getServletContext().getNamedDispatcher("/SelectAnimalServlet")
.forward(request, response);
to:
response.sendRedirect(response.encodeRedirectURL(selectAnimal));
and still the same thing blank webpage with http://localhost:8080/oosd/Relay?selectAnimal=SelectAnimalServlet link
getNamedDispatcher expects a servlet name; you're providing it with a servlet URL.
Either use the name, or use getRequestDispatcher with the URL.
Since you're forwarding, the URL will not change--there is no redirect response sent back to the browser on a forward. The contents of the forward are written directly to the original response.
Now that you're forwarding, you need to redirect to the URL, not just the name of the servlet.
What does the servlet you redirect to do for output?
I don't believe your parameter naming convention makes any sense. The parameter shouldn't be named the same as a servlet name; the parameter should be something like "command" or "select". You would then use the command parameter value to look up the URL of the servlet. Or, in your case, just prepend a /, and you're done. There's no need to do any if/else comparisons.

Spring-MVC: Is it possible to have two url-patterns for one servlet-mapping?

I have both .htm and .xml URLs that I want to be resolved as .jsp files in my WEB-INF folder. How do I specify that I want the same servlet to handle both *.htm and *.xml URLs?
Adding multiple url-pattern tags in the same mapping works for me using Spring 3.0
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/<url-pattern>
<url-pattern>*.htm</url-pattern>
<url-pattern>*.html</url-pattern>
<url-pattern>*.xml</url-pattern>
</servlet-mapping>
In regards to making your controllers resolve them to the view objects (.jsp) that you desire you can do so using controllers that extend a controller class and follow a specific naming convention or you can use annotation driven controllers. Below is an example of annotation driven controller.
#Controller
public class Controller {
#RequestMapping(value={"/","/index","/index.htm","index.html"})
public ModelAndView indexHtml() {
// RETURN VIEW (JSP) FOR HTM FILE
}
#RequestMapping(value="/index.xml")
public ModelAndView indexXML() {
// RETURN VIEW (JSP) FOR XML FILE
}
}
Yes, you can very well do that.
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>*.xml</url-pattern>
</servlet-mapping>
I assume you are talking about the <servlet-mapping> element in your "web.xml" file.
The answer is that you can (sort of) by using two <servlet-mapping> elements with different patterns for the same <servlet> element.
Note that is a feature of the Java EE Servlet specification. The associated request dispatching happens before Spring gets a look at the requests.

web.xml servlet mapping for wildcard requests

I want one of my servlets (test2) to handles the "/" request (i.e. http://localhost/), while another servlet (test1) handles all other requests ("/*").
I set up my web.xml below, but the problem is that ALL requests go to test1.jsp (even the "/" request)
Can someone tell my how to accomplish this?
<servlet>
<servlet-name>test1</servlet-name>
<jsp-file>/test1.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>test1</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>test2</servlet-name>
<jsp-file>/test2.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>test2</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
----EDIT-----
i realized my question was a bit unclear and incomplete. here is an example of exactly what i want to accomplish..
http://mytestsite.com/ -> maps to http://mytestsite.com/index.html
http://mytestsite.com/servlet1 -> runs com.mytestsite.servlet1
http://mytestsite.com/* -> maps to http://mytestsite.com/catchall.jsp (i want all other requests that aren't mapped in web.xml to map to catchall.jsp)
so my web.xml looks as follows:
<servlet>
<servlet-name>servlet1</servlet-name>
<servlet-class>com.mytestsite.servlet1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet1</servlet-name>
<url-pattern>/servlet1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>catchall</servlet-name>
<jsp-file>/catchall.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>catchall</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
so i noticed a strange problem. when i request http://mytestsite.com/, it goes to catchall.jsp before being redirected to index.html. however, it happens so quickly i wouldn't have even noticed it hitting catchall.jsp (but i put a System.out.println in this file, and it was definitely hitting it).
I think your goal is a bit confusing and brittle. However, to answer your question, try a welcome file entry for the http://your-domain.com/ request.
<welcome-file-list>
<welcome-file>/test2.jsp</welcome-file>
</welcome-file-list>
It is most common to then have test2.jsp perform a redirect or forward to some other 'controller' in your application. That way your MVC is always fired even on http://your-domain.com/ requests.
If you agree with me on that, then your welcome file should be index.jsp (to follow common conventions). The code in index.jsp is then a one-liner redirect to a 'welcome' servlet.
Use a forwarding filter instead of servlet. It's very simple to intercept "/" using such method.
filter --> /*
servlet1 --> /_some_hidden_path_1_
servlet2 --> /_some_hidden_path_2_
Really not sure about that, but maybe the order that you declare\map your servlets defines precedence. Try to declare\map test2 first and see.
Kind Regards
Try not mapping the / request to anything (get rid of the test2 servlet), and instead use a welcome file:
<welcome-file-list>
<welcome-file>
test2.jsp
</welcome-file>
</welcome-file-list>

Categories

Resources