I have two servlets defined in the web.xml file, namely the default2 and myservlet. The default2 servlet is used to map the static files like the javascript and css. The myservlet is used for getting dynamic content.
<servlet>
<servlet-name>default2</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>myservlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:my-servlet.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
The servlet mapping is defined as follows
<servlet-mapping>
<servlet-name>myservlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default2</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
When i try to access any files under /resources, i get a 404. Any ideas why this config is not working or change this config to make it work.
Tomcat's default servlet before 6.0.30 actually serves a static resource identified by HttpServletRequest.getPathInfo(), so that /style.css will be returned when /resources/style.css is requested.
Tomcat's behavior has changed from version 6.0.30 onwards. So the original configuration from the question works in newer versions of Tomcat. See "50026: Add support for mapping the default servlet to URLs other than /. (timw)" in the changelog.
Jetty's default servlet uses a full path.
It should work fine. Are those files in real also located in the /resources folder?
Your web.xml looks correct (except I would change your <load-on-startup> constants).
Make sure that your /resources exists and is a publicly visible folder in your project path and not under /WEB-INF folder.
Try changing your url-pattern for myservlet to /, and optionally adding <mvc:default-servlet-handler /> (see here) to your Spring configuration.
Removed wrong portion of the answer as per #BalusC comment.
Set a break point in your servlet and perform a debug session. Look for the path that your servlet is picking up these files at. Make sure they match the location
Related
I am trying to setup Angular 7 with a maven based back-end java project into a single war file. At the moment I am trying to configure the web.xml file where I am currently having this problem. I am not sure at all if my approach is valid or 'good' therefore I will first describe what I am trying to do (if you think better on this aspect please do correct me).
So I have a couple of JAX-RS classes which I'd like to serve as a REST API. For this purpose I have created corresponding javax.ws.rs.core.Application classes to provide these REST components. Then I am including the Application classes in the web.xml file. Below are the files:
web.xml
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>backend.backendservice.StammSolvaraJahrRestApplication</servlet-name>
<servlet-class>backend.backendservice.StammSolvaraJahrRestApplication</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>backend.backendservice.StammSolvaraJahrRestApplication</servlet-name>
<url-pattern>/rmz/*</url-pattern>
</servlet-mapping>
Another variation of web.xml that I tried
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>backend.backendservice.StammSolvaraJahrRestApplication</servlet-name>
<servlet-class>backend.backendservice.StammSolvaraJahrRestApplication</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>backend.backendservice.StammSolvaraJahrRestApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>backend.backendservice.StammSolvaraJahrRestApplication</servlet-name>
<url-pattern>/rmz/*</url-pattern>
</servlet-mapping>
Application class
public class StammSolvaraJahrRestApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> sets = new HashSet<>();
sets.add(StammSolvaraJahrRest.class);
return sets;
}
}
The error that I get is: java.lang.ClassCastException: backend.backendservice.StammSolvaraJahrRestApplication cannot be cast to javax.servlet.Servlet and if I remove the <servlet-class> then I'll get No servlet class has been specified for servlet. I am following https://docs.oracle.com/cd/E24329_01/web.1211/e24983/configure.htm#RESTF183 and How to deploy a JAX-RS application? among others but it seems not to be working.
There are two ways to define your JAX-RS servlet.
1) With Application Subclass like the one you have, you can skip the web.xml config and just add the application annotation
#ApplicationPath("resources")
public class StammSolvaraJahrRestApplication extends Application
2) With web.xml config
<servlet>
<display-name>JAX-RS Servlet</display-name>
<servlet-name>package.hierarchy.StammSolvaraJahrRestApplication</servlet-name>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>package.hierarchy.StammSolvaraJahrRestApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>JaxRSServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
If you skip the servlet mapping from the last one, it will use your your #ApplicationPath specified value, or "/resources" if the previous one is missing.
The problem is just what it says. This line in your web.xml requires a javax.servlet.Servlet:
<servlet-class>backend.backendservice.StammSolvaraJahrRestApplication</servlet-class>
Since an Application is not a javax.servlet.Servlet, you're getting the error at runtime when your XML file is processed.
If you can, I would suggest that you start with a Spring Boot starter application. Spring Boot handles all of this for you. It can even embed a Tomcat server inside a jar file so that you can run your server like a simple Java application. Doing this would save you having to worry about what you're dealing with here.
Currently, we have "root" (/) mapped to a static index.html page, but we want to upgrade to a jsp to have dynamic content. Trying to figure out how to do this. We have content that is mapped to the default content server (e.g. /css), so we don't want to change too much.
We tried:
Changing the .html to .jsp. This resulted in a blank page.
Changing the .html to .jsp and then moving the file into the WEB-INF directory. This resulted in a 404.
Trying to subclass the DefaultServlet class that content servlet is currently mapped to. This through a 500, with a class assertion error (it checked to see if it was the same class).
Adding another servlet to that url, but it overwrote the current one.
I've searched StackOverflow, but still haven't found an answer that works.
Thanks!
If I understand your question correctly, this is trivial using Spring MVC:
<mvc:default-servlet-handler/>
And in web.xml:
<servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<async-supported>true</async-supported>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/META-INF/spring/your-applicationContext-web.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Is this what you have tried already?
Just set up a controller method mapped to / that returns a view name, which is your jsp file. And make sure your view resolver is set up correctly. Any of the spring mac tutorial hellos world programs out there will show how.
How can we access web application context url from inside the CSS/JS file on java web server?
We can map URL's (for background image for example) relatively with url('../img/bg.gif') etc. but this will not work with web application with mappings like:
/shop/
/shop/show/3/
/shop/payment/
because browser will search for this file relative to current "virtual" directory.
Also, we can't universally map image URL global like url('/images/bg.gif'), because we forces deployment in top-level directory like example.com/ (not example.com/myproject/).
How to avoid changing CSS/JS(ajax) URL's when changing application context URL?
It is possible to access aplication context in CSS file in easy way like accessing contextPath in default servlet wich serves those static files?
You could do something like this (assuming you're using Tomcat, if not, look up the doc to find the correct servlet name to add the mapping):
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
Then you can add jsp el code in your css:
url('${pageContext.request.contextPath}/images/bg.gif')
This will make your CSS files serve MUCH slower, so take into account if you can do it with absolute pathing at the root. We've used this approach in an app that allowed skinning of the CSS, so that we could output custom color schemes.
I'm at the end of my rope on this one. I'm try to get a super simple webapp up and I can't seem to get tomcat to not 404 static files.
I'm using the gradle tomcat plugin with tomcat version 7.0.39
My html file is at hey-world/src/main/webapp/index.html
My web.xml looks like this:
<servlet>
<servlet-name>Resteasy</servlet-name>
<servlet-class>
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>HeyWorldApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
So I thought this setup would map localhost:8080/hey-world/static/index.html to the file, but it 404's everytime. Is this a problem with some convention in the gradle tomcat plugin?
The URL-patterns used in web.xml/servlet-mapping is often a little simplistic. I think in your case, the /* pattern for Resteasy will work as a catch-all, so that no other mapping will really matter.
For debugging, I suggest you remove the Resteasy-servlet altogether, and see if you can serve static files from a custom URL with your mapping.
If that works, re-enable Resteasy, but on a different URL-pattern (eg. /rest/*).
If that works, well, then everything really works fine, it's just that the URL-mapping for /* blocks anything else from working.
The easiest solution would probably be to server static files as per default (no mapping), and serve rest-stuff from another URL.
Alternatively use two web apps. One with context root /static, one with context root /.
I am writing an application in JSP, and I need to remove the ".jsp" extension from the URL. For example, I need:
http://example.com/search.jsp?q=stackoverflow
To be:
http://example.com/search?q=stackoverflow
I know that this can be done using the ".htaccess" file, but I need some other way. I have tried the following code:
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.</url-pattern>
</servlet-mapping>
However, this did not work. Does anyone have some suggestions for ways to accomplish this? Thanks in advance for any help.
With a servlet mapping you need to specify each JSP individually like follows:
<servlet>
<servlet-name>search</servlet-name>
<jsp-file>/search.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>search</servlet-name>
<url-pattern>/search</url-pattern>
</servlet-mapping>
It's easier if all those JSPs are in a common path. E.g. /app/*.
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>com.example.FriendlyURLServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
with
request.getRequestDispatcher("/WEB-INF" + request.getPathInfo() + ".jsp").forward(request, response);
This assumes the JSPs to be in /WEB-INF folder so that they cannot be requested directly. This will show /WEB-INF/search.jsp on http://example.com/app/search.
Alternatively, you can use Tuckey's URLRewriteFilter. It's much similar to Apache HTTPD's mod_rewrite.