welcome-file-list not working in jetty + spring - java

I'm using Jetty 8.1.4 with Spring 3.2.4. Following is my web.xml file. I have an index.html file under WEB-INF and I want that page to be hit when I do http://myapp.com/ or simple http://myapp.com but I'm getting 404. If I do http://myapp.com/index.html it works. I'm not sure what I'm missing. Also, I'm bit confused if I must use / or /* in the url-pattern below, I tried both.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
id="DOMAINAPPROVALGUI" version="2.4"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>myapp-ui</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/myapp-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<session-config>
<session-timeout>10</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>myappname</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>myappname</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

Jetty 8 is EOL (End of Life), upgrade to Jetty 9. (The answer here is provided based on how Jetty 9 operates.)
The <welcome-file-list> is part of the DefaultServlet handling (per servlet spec).
Your declaration of myappname at <url-pattern>/*</url-pattern> is effectively preventing the DefaultServlet from doing anything.
Your configuration has basically said "send all requests to my DispatcherServlet".
This even includes static file serving, welcome-file handling, default handling, error handling, dispatching, and much much more.
As for what url pattern to choose, that's up to you.
There are many ways to use Spring, your current configuration at /* is just as valid as others that have it at *.do or *.dispatch or /dispatch/*
You have to decide what is best for your webapp, and adjust your internal use of Spring to satisfy your needs (such as how you declare your RequestMapping's)
Now that you know why <welcome-file-list> isn't working, you can make adjustments to either not use the standard servlet <welcome-file-list> (using something internally in Spring), or adjust your dispatcher servlet url pattern to allow the servlet container (Jetty) to serve your static files and handle your declared <welcome-file-list>.

I added below to my servlet.xml to make this work. Agree with #Joakim Erdfelt answer that request went to spring. But not sure how directly entering index.html in url worked.
<mvc:view-controller path=”/” view-name=”index” />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/" />
<property name="suffix" value=".html" />
</bean>

Firstly, Your servlet mapping config of spring is not right , it will mapping all thing and link to spring , this means that *.jsp would be handled by spring. So You Should fix this flaw config. But after doing this, it still would not be right to access the welcome page. this is a character of Jetty.
I Must Say: there is some difference between tomcat and jetty. Tomcat can handle this with right behaviour but jetty not.
You can try to verify by below step.
delete the mapping with "/"
and run the app with tomcat and jetty. you can find out tomcat and jetty both works.
if you add a servlet mapping with mapping pattern : "/" ,either with a customer servlet or spring dispatch servlet. it will work right in tomcat but jetty not.

i think placing you welcome file at the start will help you to load the file.To be precise place it after the display tag

Related

How to intercept a url and redirect it to a jsp page?

I want to develop a application and deploy in WebSphere where the requirement is:
if there are any request like http://appserver1:9080/ - it will reach to a landing jsp page
for example http://appserver1:9080/index.jsp
Is it at all possible to redirect to a page even if I don't mention
the resource name?
If you want to redirect from server's root, this is not about your java code or project configuration, it is about server configuration.
Look here for WebSphere configuration.
For JEE projects, on web.xml, you can define as;
<web-app>
....
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
</welcome-file-list>
</web-app>
So
http://localhost:8080/myproject
will load index.jsp
Source for details
From what you are describing, the redirection can be pretty much handled by servlets mapping. Read here:
https://docs.oracle.com/cd/E13222_01/wls/docs92/webapp/configureservlet.html
You can be able to intercept URL requests and process:
// Servlet definition on your web.xml
<servlet>
<servlet-name>ServletHandler</servlet-name>
<servlet-class>com.servlets.ServletHandler</servlet-class>
</servlet>
// This maps all requests to the above defined servlet for processing:
<servlet-mapping>
<servlet-name>ServletHandler</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
I hope this helps
You can define welcome files in web.xml
<web-app>
...
<welcome-file-list>
<welcome-file>index.jsp/welcome-file>
</welcome-file-list>
...
</web-app>
But according to the spec index.html, index.htm and index.jsp are welcome files by default. So you probably don't need to configure anything when the file is called index.jsp.

Spring MVC url pattern - keeps appending the controller

I have a Spring MVC app.
This is the web.xml
<xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring Web MVC Application</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
</web-app>
I have a sample page Controller (TestController). with request mapping
#RequestMapping("/Test")
class TestController{
}
Am calling the controller using Test
When I click the link first time, its working fine
http://localhost:8008/App/Test
If i click the link, once again, it is appending Test once again
http://localhost:8008/App/Test/Test
and it keeps adding.
What could be the issue!
Instead of having
link
in your JSP, you should have
link
(and of course add the JSTL core taglib definition to the head of the JSP).
This will make use of an absolute URL (/App/Test) rather than a relative one (Test), and will automatically prepend the context path of the application (/App in your case) to the URL. This link can be used from anywhere in the application, and will always poit to your controller, whatever the URL of the current page is.
Another way is to use
link
but it's longer, less clean, and doesn't allow adding parameters to the URL like c:url does. Note that Spring also has an s:url tag that does the same thing, and more.
An addition to #JB Nizet's answer, since it is not clear which viewResolver you are using and there might be other people looking for an answer to that question:
if you are using freemarker as a template engine, you can do that:
link
in your templates. This will let spring create the correct context path for you.
url is the name of the macro here, and spring the reference name of the template.
Note: you have to import the spring.ftl-template for that beforehand, like so
<#import "spring.ftl" as spring/>
before you can use the macro.

JSP Login Authentication Script failing (MySQL-backend) web.xml servlet mapping?

I am just starting out with JSP in NetBeans 6.9.1 and im trying to make a basic login script for user authentication (sessions will be added later; These are made automatically for every JSP page right?)
The problem I am having is the following.
I followed the tutorial at:
http://www.roseindia.net/jsp/loginbean.shtml
** I made the necessary changes (Database related) **
When running the project I get the login screen presented, as it should.
Although when filling out the details for database authentication, I keep on running into a 404 error: "descriptionThe requested resource () is not available."
I think the problem might be lying in my web.xml for not mapping the servlets right.
(This was not mentioned in the tutorial though.)
See below for my web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" <CANT POST namespace hyperlinks. New user...>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Login</servlet-name>
<servlet-class>Login</servlet-class>
</servlet>
<servlet>
<servlet-name>LoginBean</servlet-name>
<servlet-class>Login</servlet-class>
</servlet>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>Login.jsp</welcome-file>
</welcome-file-list>
</web-app>
I hope you guys have time to look at it!
(First time posting here so if there is anything im doing wrong, please let me know.
Regards,
B.
First of all, roseindia.net is the worst source ever to learn Java EE (JSP/Servlet/JSF/etc). Its tutorials are cluttered of bad practices and do in no way explain/use the basic concepts properly. It's maintained by copypaste-addicted amateurs with advertisement incomes as #1 priority. For me, that side is ridiculous, but for new-to-Java EE users it may be very misleading because they don't know what's good or bad.
Your functional requirement is sound, but the posted web.xml makes no sense. Firstly, you seem to have declared an ordinary Javabean class (which does not extends HttpServlet) as a Servlet. Secondly, the class is not been placed inside a package, although this may not be the root cause of your problem, packageless classes are invisible to other classes inside a package and instantiating them will only work in very specific environments.
Further I also see the FacesServlet being declared in web.xml. This is part of JSF, a component based MVC framework which is designed on top of Servlet API and can use JSP files as views.
What do you want? Develop a login page using JSF or using "plain" JSP/Servlet?
Anyway, I strongly recommend to blacklist roseindia.net as a learning source and continue with proper tutorials and books. E.g. the tutorials provided by Oracle itself and the JSF2 - The Complete Refernce book of JSF spec lead himself. Further details about tutorials and books depends on whether you'd like to use JSF or not.
See also:
Java web development, what skills do I need?
What is the difference between JSP, Servlet and JSF?

How to access static resources when mapping a global front controller servlet on /*

I've mapped the Spring MVC dispatcher as a global front controller servlet on /*.
<servlet>
<servlet-name>home</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>home</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
However, this mapping stops the access to static files like CSS, JS, images etc which are all in the /res/ folder.
How can I access them anyway?
Map the controller servlet on a more specific url-pattern like /pages/*, put the static content in a specific folder like /static and create a Filter listening on /* which transparently continues the chain for any static content and dispatches requests to the controller servlet for other content.
In a nutshell:
<filter>
<filter-name>filter</filter-name>
<filter-class>com.example.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>controller</servlet-name>
<servlet-class>com.example.Controller</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>controller</servlet-name>
<url-pattern>/pages/*</url-pattern>
</servlet-mapping>
with the following in filter's doFilter():
HttpServletRequest req = (HttpServletRequest) request;
String path = req.getRequestURI().substring(req.getContextPath().length());
if (path.startsWith("/static")) {
chain.doFilter(request, response); // Goes to default servlet.
} else {
request.getRequestDispatcher("/pages" + path).forward(request, response);
}
No, this does not end up with /pages in browser address bar. It's fully transparent. You can if necessary make "/static" and/or "/pages" an init-param of the filter.
With Spring 3.0.4.RELEASE and higher you can use
<mvc:resources mapping="/resources/**" location="/public-resources/"/>
As seen in Spring Reference.
What you do is add a welcome file in your web.xml
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
And then add this to your servlet mappings so that when someone goes to the root of your application, they get sent to index.html internally and then the mapping will internally send them to the servlet you map it to
<servlet-mapping>
<servlet-name>MainActions</servlet-name>
<url-pattern>/main</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>MainActions</servlet-name>
<url-pattern>/index.html</url-pattern>
</servlet-mapping>
End result: You visit /Application, but you are presented with /Application/MainActions servlet without disrupting any other root requests.
Get it? So your app still sits at a sub url, but automatically gets presented when the user goes to the root of your site. This allows you to have the /images/bob.img still go to the regular place, but '/' is your app.
If you use Tomcat, you can map resources to the default servlet:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
and access your resources with url http://{context path}/static/res/...
Also works with Jetty, not sure about other servlet containers.
Serving static content with appropriate suffix in multiple servlet-mapping definitions solved the security issue which is mentioned in one of the comments in one of the answers posted. Quoted below:
This was a security hole in Tomcat (WEB-INF and META-INF contents are accessible this way) and it has been fixed in 7.0.4 (and will be ported to 5.x and 6.x as well). – BalusC Nov 2 '10 at 22:44
which helped me a lot.
And here is how I solved it:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
I've run into this also and never found a great solution. I ended up mapping my servlet one level higher in the URL hierarchy:
<servlet-mapping>
<servlet-name>home</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
And now everything at the base context (and in your /res directory) can be served up by your container.
As of 3.0.4 you should be able to use mvc:resources in combination with mvc:default-servlet-handler as described in the spring documentation to achieve this.
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-static-resources
The reason for the collision seems to be because, by default, the context root, "/", is to be handled by org.apache.catalina.servlets.DefaultServlet. This servlet is intended to handle requests for static resources.
If you decide to bump it out of the way with your own servlet, with the intent of handling dynamic requests, that top-level servlet must also carry out any tasks accomplished by catalina's original "DefaultServlet" handler.
If you read through the tomcat docs, they make mention that True Apache (httpd) is better than Apache Tomcat for handling static content, since it is purpose built to do just that. My guess is because Tomcat by default uses org.apache.catalina.servlets.DefaultServlet to handle static requests. Since it's all wrapped up in a JVM, and Tomcat is intended to as a Servlet/JSP container, they probably didn't write that class as a super-optimized static content handler. It's there. It gets the job done. Good enough.
But that's the thing that handles static content and it lives at "/". So if you put anything else there, and that thing doesn't handle static requests, WHOOPS, there goes your static resources.
I've been searching high and low for the same answer and the answer I'm getting everywhere is "if you don't want it to do that, don't do that".
So long story short, your configuration is displacing the default static resource handler with something that isn't a static resource handler at all. You'll need to try a different configuration to get the results you're looking for (as will I).
'Static' files in App Engine aren't directly accessible by your app. You either need to upload them twice, or serve the static files yourself, rather than using a static handler.
The best way to handle this is using some kind of URL re-writing. In this way, you can have clean restful URLs, and NOT with any extensions i.e abc.com/welcom/register as opposed to abc.com/welcome/resister.html
I use Tuckey URL which is pretty cool.
It's got instructions on how to set up your web app.I have set it up with my Spring MVC web app. Of course, everything was fine until I wanted to use annotations for Spring 3 validations like #Email or #Null for domain objects.
When I add the Spring mvc directives:
< mvc:annotation-driven />
< mvc:default-servlet-handler />
.. it breaks the good ol Tuckey code. Apparently, < mvc:default-servlet-handler /> replaces Tuckey, which I'm still trying to solve.
I'd recommend trying to use a Filter instead of a default servlet whenever possible.
Other two possibilities:
Write a FileServlet yourself. You'll find plenty examples, it should just open the file by URL and write its contents into output stream. Then, use it to serve static file request.
Instantiate a FileServlet class used by Google App Engine and call service(request, response) on that FileServlet when you need to serve the static file at a given URL.
You can map /res/* to YourFileServlet or whatever to exclude it from DispatcherServlets' handling, or call it directly from DispatcherServlet.
And, I have to ask, what does Spring documentation say about this collision? I've never used it.
Add the folders which you don't want to trigger servlet processing to the <static-files> section of your appengine-web.xml file.
I just did this and looks like things are starting to work ok. Here's my structure:
/
/pages/<.jsp files>
/css
I added "/pages/**" and "/css/**" to the <static-files> section and I can now forward to a .jsp file from inside a servlet doGet without causing an infinite loop.
After trying the filter approach without success (it did for some reason not enter the doFilter() function) I changed my setup a bit and found a very simple solution for the root serving problem:
Instead of serving " / * "
in my main Servlet, I now only listen to dedicated language prefixes
"EN", "EN/ *", "DE", "DE/ *"
Static content gets served by the default Servlet and the empty root requests go to the index.jsp which calls up my main Servlet with the default language:
< jsp:include page="/EN/" />
(no other content on the index page.)
I found that using
<mvc:default-servlet-handler />
in the spring MVC servlet bean definition file works for me. It passes any request that isn't handled by a registered MVC controller on to the container's original default handler, which should serve it as static content. Just make sure you have no controller registered that handles everything, and it should work just fine. Not sure why #logixplayer suggests URL rewriting; you can achieve the effect he's looking for just adequately using Spring MVC alone.
I found a simpler solution with a dummy index file.
Create a Servlet (or use the one you wanted to respond to "/") which maps to "/index.html"
(Solutions mentioned here use the mapping via XML, I used the 3.0 version with annotation #WebServlet)
Then create a static (empty) file at the root of the static content named "index.html"
I was using Jetty, and what happened was that the server recognized the file instead of listing the directory but when asked for the resource, my Servlet took control instead. All other static content remained unaffected.
In Embedded Jetty I managed to achieve something similar by adding a mapping for the "css" directory in web.xml. Explicitly telling it to use DefaultServlet:
<servlet>
<servlet-name>DefaultServlet</servlet-name>
<servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DefaultServlet</servlet-name>
<url-pattern>/css/*</url-pattern>
</servlet-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<mvc:default-servlet-handler/>
</beans>
and if you want to use annotation based configuration use below code
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
With regard to Tomcat, a lot depends on the particular version. There was a bug fix
https://bz.apache.org/bugzilla/show_bug.cgi?id=50026
which means the servlet-mapping (other than for '/') for the default servlet behaves differently in Tomcat 6.0.29 (and earlier) compared with later versions.
In section "12.2 Specification of Mappings" of the Servlet Specification, it says:
A string containing only the ’/’ character indicates the "default" servlet of the
application.
So in theory, you could make your Servlet mapped to /* do:
getServletContext().getNamedDispatcher("/").forward(req,res);
... if you didn't want to handle it yourself.
However, in practice, it doesn't work.
In both Tomcat and Jetty, the call to getServletContext().getNamedDispatcher('/') returns null if there is a servlet mapped to '/*'

EL in a JSP stopped evaluating

In a JSP page(index.jsp):
${requestContext.requestURL} is the URL
just shows the expression itself. It used to be evaluated to something like "http://.../somerset/"
I created the Maven project with maven-archetype-webapp archetype in Eclipse. The Jetty version is jetty-6.1.14.
My web.xml is simple:
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>SomersetServlet</servlet-name>
<display-name>SomersetServlet</display-name>
<description></description>
<servlet-class>com.foo.somerset.SomersetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SomersetServlet</servlet-name>
<url-pattern>/som.do</url-pattern>
</servlet-mapping>
</web-app>
See Javascript String.replace(/\$/,str) works weirdly in jsp file for some possible reasons.
Your web.xml should contain reference to web-app_2_4.xsd schema, like
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
This enables servlet 2.4 and jsp 2.0 processing, which includes EL.
Btw requestContext is not valid implicit object.
Incorrectly matched quotes can cause this behavior, where the expression just gets treated as a string. Your IDE would normally highlight this in a different color if this is the case.
Be sure you have directive, and other libraries you use included
<jsp:root .....
More info on definition here
http://java.sun.com/products/jsp/tags/12/syntaxref123.html

Categories