problem with very first spring project - spring-mvc

I just switched from Striped to Spring but i'm having issues with my very first project,
Basically i get the 404 from the server.
Strange enough, i have followed one by one all the steps in my book.
I use Eclipse, Tomcat 6 and Spring 2.5
The structure of my project is like so:
src>
controllers(package)>SpringTestController(implements controller).....then
......web content>jsp(folder)>hello.jsp.....then....web-content>web-inf>SpringTest-servlet.xml and web.xml
inside lib i have the 9 necessary jars.
my controller:
public class SpringTestController implements Controller{
public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
return new ModelAndView("jsp/hello.jsp");
}
}
my SpringTest-servet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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-2.5.xsd">
<bean name="/hello.htm" class="controllers.SpringTestController"/>
</beans>
my web.xml(without header to save space)
<servlet>
<servlet-name>SpringTest</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringTest</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
Where do you think the problem could be?
I have been trying to look around the files but beside web.xml "where i dont see any abnormality" i'm very new to this flow structure so i really cannot get where the problem is.
Thx for your time

I'm suspicious of the practice of using the name attribute of bean to specify URL paths - while I'm sure it's probably possible, my answer will tell you how to do it using more traditional means.
First of all, here is the new SpringTest-servlet.xml:
<bean id="helloController" class="controllers.SpringTestController" />
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/hello.htm">helloController</prop>
</props>
</property>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
You'll probably notice a few things. I'm using the id attribute of bean to define your controller so it can be referenced elsewhere (in the urlMapping bean as you're about to see).
I define a urlMapping bean, which does exactly what you think it does - maps requests (e.g. /hello.htm) to a controller bean.
I've also used viewResolver to map views names to view files, however that is a personal preference thing. Since I'm now using a view resolver, your controller looks like this:
public class SpringTestController implements Controller {
#Override
public ModelAndView handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Exception {
return new ModelAndView("hello");
}
}
I don't need to put the path to the view because the viewResolver prepends it with "/WEB-INF/jsp/" and adds ".jsp" to the end. You can change the prefix to wherever you store your view files, or you can not use it at all. It's a personal preference thing, though I like to use it :)
Sorry if this answer didn't conform to your style - I tried to get it working your way and couldn't, so this is how I normally set up a Spring project (if I'm not using annotations).
Hope this helps.

Related

url-pattern not working in spring mvc application

I had made a basic application on spring mvc framework.
when i write the following url pattern on web.xml:
<servlet-mapping>
<servlet-name>springxml</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
and runs the application (using ../SpringMVCXML/welcome.jsp) , it displays HTTP Status 404 error.
When I changes the url pattern other than .jsp, application is running fine.
Why Application is not running on .jsp url pattern?
I had used following java class act as controller.
#Controller
#RequestMapping(value="/welcome",method=RequestMethod.GET)
public class ControllerHello {
#RequestMapping(method=RequestMethod.GET)
public String printHello(ModelMap map) {
map.addAttribute("message", "Hello Spring MVC Framework");
return "hello";
}
}
Also, my springxml-servlet.xml had following code:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
Assuming you have also springxml servlet is also serving other views than *.jsp (you might have other servlet-mappings in your web.xml), the situation is as follows:
You registered a controller for the path /welcome, not for /welcome.jsp. Therefore, /welcome.jsp is not mapped to a Spring mvc controller.
The /welcome HelloController will give you the String output hello.
/welcome.jsp will give an error 404, since it is in WEB-INF and there is no Spring MVC controller for that url.
The org.springframework.web.servlet.view.InternalResourceViewResolver is meant to put your jsp files inside /WEB-INF. Look at http://www.mkyong.com/spring-mvc/spring-mvc-internalresourceviewresolver-example/ for a simple explanation for what the InternalResourceResolver does. Basically, it enables Spring MVC to use a jsp, that is not in your public resources, as a view.
It is not a mechanism to register these jsps as valid urls.
The urls are determined in the requestmappings.
you probably do not have any spring controller mapping to this URL /welcome.jsp
what version of spring you are using? if you are using spring 2.5 or above, try following code
#RequestMapping(value = "welcome.jsp")
public String welcomeJSP(){
return "welcome";
}

About spring mvc annotation use properties files

You know we can use properties files data in Spring mvc xml file.
for example:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>xxxx.properties</value>
</property>
</bean>
...
<mvc:mapping path="/${path}/*" />
...
but how I could use it in annotation
like:
#Controller
#RequestMapping("/${url}")
now it's wrong.
Tell me how to do
Thank you very much.
Spring doesnt resolve ${x} inside #RequestMapping, indeed {x} is used for #PathVariable. It's not possible to pass non-constant variables to annotations so you can't use #Value either.
I believe its not possible to do what you intend through annotations.

Spring MVC : using wildcards in <mvc:resources>

I'm implementing a cache busting system for a Spring MVC application.
For this system to work, I have to strip the "cache busting code" from a given url. Let's say my generated cache busting code is "123" and I have a .css url that is: /public-123/css/style.css. In this example, I want /public/css/style.css to be succesfully called (-123 must be stripped).
This works in my "mvc-config.xml" context file:
<mvc:resources mapping="/public-123/**" location="/public/" />
But I would also like any cache busting code to work, even if it's not the current one. For example, I would also like /public-456/css/style.css to reach the style.css file.
If I try to add another wildcard to the mapping:
<mvc:resources mapping="/public-*/**" location="/public/" />
It doesn't work! I receive a 404....
How could I specify the "mapping" attribute so any code after the "public-" part is well managed?
One way to handle this is to use Spring EL, as shown in the Spring docs:
<mvc:resources mapping="/resources-#{applicationProps['application.version']}/**" location="/public-resources/"/>
You could probably store the "123" part in a properties file so it only gets set once. E.g. via property-placeholder:
<context:property-placeholder location="classpath:myApp.properties"/>
<mvc:resources mapping="/resources-${cache.code}/**" location="/public-resources/"/>
This has the advantage of being able to read this code in your JSP pages (to generate links) via the same properties value.
I managed to get this working by manually defining the ResourceHttpRequestHandler to handle assets that are located on the filesystem alongside the <mvc:resources /> tag:
<bean id="assetsResourceHandler" class="org.springframework.web.servlet.resource.ResourceHttpRequestHandler">
<property name="locations">
<list>
<bean class="org.springframework.core.io.UrlResource">
<constructor-arg value="file:#{applicationProps['assets.basedir']}"></constructor-arg>
</bean>
</list>
</property>
</bean>
I guess you're doing this to achieve cache busting for your static resources.
In the meantime, Spring 4.1 has dedicated features for this, so you can remove a lot of that custom configuration.
Something like this:
<mvc:resources mapping="/public/**" location="/public/"/>
<mvc:resource-chain resource-cache="true">
<mvc:resolvers>
<mvc:version-resolver>
<mvc:content-version-strategy patterns="/**"/>
</mvc:version-resolver>
</mvc:resolvers>
</mvc:resource-chain>
</mvc:resources>

How to override urlpattern in web.xml

I am working on a Spring MVC project incorporating Tiles.
Here is the current urlPattern in the web.xml.
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
In the spring configuration file, currently the only view resolver is.
<bean id="viewResolver"
class="org.springframework.web.servlet.view.ResourceBundleViewResolver"
p:basename="views" />
<bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles2.TilesConfigurer"
p:definitions="/WEB-INF/tiles-defs.xml" />
In my controller, the only way the request mapping works is if I enter in /sample.html which routs to the proper controller. What I need to do is have the current view /sample to map to the proper controller. Is there a way to do this. Would internalviewresolver or an entry change in the views.properties file be the answer? Thanks.
No, you have to change the servlet url-pattern. Map it to /

Spring MVC: How to resolve the path to subdirectories of the root 'JSP' folder in a web application

What is a simple way to resolve the path to a JSP file that is not located in the root JSP directory of a web application using SpringMVCs viewResolvers? For example, suppose we have the following web application structure:
web-app
|-WEB-INF
|-jsp
|-secure
|-admin.jsp
|-admin2.jsp
index.jsp
login.jsp
I would like to use some out-of-the-box components to resolve the JSP files within the jsp root folder and the secure subdirectory. I have a *-servlet.xml file that defines:
an out-of-the-box, InternalResourceViewResolver:
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
a handler mapping:
<bean id="handlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/index.htm">urlFilenameViewController</prop>
<prop key="/login.htm">urlFilenameViewController</prop>
<prop key="/secure/**">urlFilenameViewController</prop>
</props>
</property>
</bean>
an out-of-the-box UrlFilenameViewController controller:
<bean id="urlFilenameViewController" class="org.springframework.web.servlet.mvc.UrlFilenameViewController">
</bean>
The problem I have is that requests to the JSPs in the secure directory cannot be resolved, as the jspViewResolver only has a prefix defined as /jsp/ and not /jsp/secure/.
Is there a way to handle subdirectories like this? I would prefer to keep this structure because I'm also trying to make use of Spring Security and having all secure pages in a subdirectory is a nice way to do this.
There's probably a simple way to acheive this but I'm new to Spring and the Spring MVC framework so any pointers would be appreciated.
I haven't been able to discover the exact solution to the question I asked but I do have a workaround that suits my particular requirements. The problem seems to lie in the hander mapping. If specified as in the example in the post, any requests to pages in the secure folder result in a failed attempt to locate the actual JSP file in the /WEB-INF/JSP/ folder when of course the actual file is located in /WEB-INF/jsp/secure/.
However, if specified like so:
<bean id="handlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/login.htm">loginFormController</prop>
<prop key="**/*.htm">urlFilenameViewController</prop>
</props>
</property>
</bean>
Then all the pages are resolved correctly. A request to /login.html will go to a specific form controller but requests to all other pages, no matter whether they are in the root JSP directory or a sub directory will be found. For me this is fine because what I was really looking for was a way to avoid specifiying a controller for every page in the application (hmmm... perhaps I should have made that clear in the first post - and perhaps there are better ways to do this anyway(?)) . The **/*.htm acts as a catch-all case and any pages that I want handled by a different controller can be specified explicitly above this property, as demonstrated by /login.htm.
Try with UrlFilenameViewController or return new ModelAndView("secure/login");
You can try giving names of the views in the Controller like
<property name="formView" value="secure/admin"/>
<property name="successView" value="secure/admin2"/>
having prefix and suffix mapped as below
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
This will eventually map to /WEB-INF/jsp/secure/admin.jsp and /WEB-INF/jsp/secure/admin2.jsp
You need to set the alwaysUseFullPath property in in the Handler to true:
<bean id="handlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
...
<property name="alwaysUseFullPath" value="true" />
</bean>
This will force the handler to use the '/secure/' part of the URI and then the resolver will include it when looking for a JSP in WEB-INF/jsp.
It seems like this ought to work, according to the docs:
http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/web/servlet/mvc/UrlFilenameViewController.html
The configs you have shown seem to match up with the examples in the doc. If your Spring MVC dispatcher servlet is mapped to "/" then requests to "{context}/secure/whatever.jsp" should get translated to view name "secure/whatever". Maybe it has something to do with the "**" wildcard? Or maybe some of your other configs are not right? Can you include the portion of your web.xml where you set up your Spring dispatcher servlet and also include the full paths you're requesting in your browser?
Another way to find the problem would be to to download the Spring MVC source code and include it in your app, then use a debugger to see exactly what is going on in both the SimpleUrlHandlerMapping and UrlFilenameViewController beans to try to pinpoint the error. You should be able to pretty quickly determine where things are going wrong that way.
You need to set the property as follows:
<property name="prefix" value="/WEB-INF/jsp/"/>
and then you can access the URI secure/admin1.jsp
All sub folders can be accessed by using wild card in prefix
From controller you can simply return jsp name as string and the jsp will be displayed even if it is under sub folders of /WEB-INF/jsp/ like /WEB-INF/jsp/abc

Resources