How can I make an exception to /* url-pattern in web.xml? - java

In our web.xml, we have CXFServlet mapped to the /* url pattern:
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
This works great and we don't want to change it at this point. But I would like to have an html page (/admin/index.html) that is not handled by the CXFServlet, and is just served up directly as html. How can I accomplish this? I don't know how to create a servlet mapping just to serve an html page.
Note we are using IBM WebSphere 8 (WAS 8) if that matters.

You can try:
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/admin/*</url-pattern>
</servlet-mapping>
It work's in Jetty and Tomcat.

None of the given answers (so far) met my requirements, but I found a simple solution that did.
For some reason it turns out that WebSphere will handle JSPs itself, rather than delegating to the servlet that has the /* mapping -- even though there is no specific mapping in web.xml mentioning JSPs. Maybe this is part of the spec and one would have to explicitly map *.jsp to a servlet if you want it to handle those requests?
In any case it works for me -- instead of using /admin/index.html I can use /admin/index.jsp (and will probably add index.jsp to welcome-file-list so that requests for /admin will also give this page).

You can have some code in CXFServlet.java
In doget() methods:
URL url = new URL(request.getRequestURL());
System.out.println("URL is:" + url);
if (url.toString().contains("/admin/")) {
response.setContentType("text/html; charset=UTF-8");
PrintWriter pw = response.getWriter();
pw.print("<!DOCTYPE html><html lang=\"fa\" dir=\"rtl\">\n"
+ "<head>"
+ "<meta charset=\"utf-8\"/>"
+ "</head>"
+ "<body>"
+ "<div>some thing</div>"
+ "<body></html>");
pw.close();
return;
}

Related

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>?

create servlet url-pattern with "/"

I've created servlet named MainContent. and I have such mapping
<servlet>
<display-name>MainContent</display-name>
<servlet-name>MainContent</servlet-name>
<servlet-class>ge.test.servlet.MainContent</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MainContent</servlet-name>
<url-pattern>/main</url-pattern>
</servlet-mapping>
so, when I go to the link:
//localhost:8080/MyAppl/main I enter into the servlets doGet() method. Then I create RequestDispatcher forward to the index.jsp.
everything works!
RequestDispatcher rd = context.getRequestDispatcher("/index.jsp?language="+ lang);
rd.forward(request, response);
everything works!
Question:
Now I need to change url-pattern. I need something like that-:when I enter to the localhost:8080/MyAppl/ I need to be redirected to my servlet.
So I create something like that:
<url-pattern>/</url-pattern>
ok, it works! I'm redirected to the servlet. but something wrong happend here. when Servlet created RequestDispatcher forward , there was no images and css in my index.jsp.
when I see in the firebug console, I've seen that errors:
Resource interpreted as Stylesheet but transferred with MIME type text/html: "http://localhost:8080/MyApp/font/font_big.css". localhost/:15
Resource interpreted as Image but transferred with MIME type text/html: "http://localhost:8080/MyApp/IMG/company.gif".
How can I fix that?
Yes, like #DwB pointed, '/' context is problematic URL pattern and it causes your problem.
Use
<servlet-mapping>
<servlet-name>MainServlet</servlet-name>
<url-pattern></url-pattern>
</servlet-mapping>
instead. It is "the servlet 3.0 way" to do this.
Sources
[1] http://www.coderanch.com/t/366340/Servlets/java/servlet-mapping-url-pattern
[2] How can I map a "root" Servlet so that other scripts are still runnable?

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.

Java JSP/Servlet: controller servlet throwing the famous stack overflow

I've read several docs and I don't get it: I know I'm doing something wrong but I don't understand what. I've got a website that is entirely dynamically generated: there's hardly any static content at all.
So, trying to understand JSP/Servlet, I've written my own "front controller" intercepting every single query, it looks like this:
<servlet-mapping>
<servlet-name>defaultservlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Basically I want any user request, like:
example.org
example.org/bar
example.org/foo.html
to all go through a default servlet which I've written.
The servlet then examines the URI and find to which .jsp the request must be dispatched, and then does, after having set all the attributes correctly, a:
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/WEB-INF/jsp/index.jsp");
dispatcher.forward(req, resp);
When I'm using a url-pattern (in web.xml) like, say, *.html, everything works fine. But when I change it to /* (to really intercept everything), I enter an endless loop and it ends up with a... StackOverflow :)
When the request is dispatched, is the URI ".../WEB-INF/jsp/index.jsp" itself matched by the web.xml filter /* that I set?
EDIT apparently, no, because this is an exact mapping to index.jsp and hence it bypasses the web.xml url-pattern. So I still don't get how I can enter that endless loop.
How should I do if I want to intercept everything using a /* url-pattern and yet be able to dispatch/forward/?
I'm not asking about specs/Javadocs here: I'm really confused about the bigger picture and I'd need some explanation as to what could be going on.
Am I not supposed to intercept really everything?
If I can intercept everything, what should I be aware of regarding forwarding/dispatching?
Unfortunately, Serlvet spec doesn't allow to create a servlet mapping to match only incoming request, not forwards. However, this can be done for filter mappings (and by default filter mappings match only incoming requests).
So, the typical solution for intercepting everything with a single servlet is to use a UrlRewriteFilter:
<filter>
<filter-name>urlRewrite</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>urlRewrite</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>application</servlet-name>
<servlet-class>...</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>application</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
/WEB-INF/urlrewrite.xml:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite
PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN"
"http://tuckey.org/res/dtds/urlrewrite3.0.dtd">
<urlrewrite default-match-type="wildcard">
<rule>
<from>/**</from>
<to>/app/$1</to>
</rule>
<outbound-rule>
<from>/app/**</from>
<to>/$1</to>
</outbound-rule>
</urlrewrite>
This way also allows you to specify exceptions from /* mapping for static files.
Try using struts in which front controller pattern is inbuilt. There you will have a action class and you can define forwards in struts-config file using which you can easily manage the forwards.
Go through the tutorial http://www.roseindia.net/struts/struts2/index.shtml. Hope this helps you.

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