I'm a newbie with Spring and web MVC module. Basically, i have the following :
web.xml
<servlet>
<servlet-name>abc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>abc-dispatcher</servlet-name>
<url-pattern>/user/*</url-pattern>
</servlet-mapping>
abc-dispatcher-servlet.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="myPkg" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
And i have a controller, related parts are :
#Controller
public class ABCController {
#RequestMapping("/user/welcome")
public String printWelcome(ModelMap model) {
//code
}
Now whenever i try to access http://localhost:8080/myapp/user/welcome
it gives me 404.
Logs say that "mapped url '/user/welcome' onto handler 'ABCController' but it failed to map URI [/MYAPP/user/welcome] in DispatcherServlet with name 'abc-dispatcher' .
Totally confused. I have checked all the threads where we specify a mapping twice, but that's not the case here. I must be missing something!
Thanks for the help!
The URL should be http://localhost:8080/myapp/user/user/welcome. Indeed, unless the alwaysUseFullPath property of the handler is set to true, the servlet-mapping is prepended to the request mapping URL to form the full path.
See http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#mvc-handlermapping for details:
alwaysUseFullPath
If true , Spring uses the full path within the current Servlet context to find an appropriate handler. If false (the default), the
path within the current Servlet mapping is used. For example, if a
Servlet is mapped using /testing/* and the alwaysUseFullPath property
is set to true, /testing/viewPage.html is used, whereas if the
property is set to false, /viewPage.html is used.
It's' been added context:component-scan element into the sample context file snippet but there is no <annotation-driven/> element that says spring framework to look for controllers annotated with #Controller
For me, the problem was that I was using the deprecated DefaultAnnotationHandlerMapping, and even if setting the alwaysUseFullPath to true, it didn't take effect, however replacing DefaultAnnotationHandlerMapping in benefit of RequestMappingHandlerMapping with the alwaysUseFullPath set to true solved the problem.
<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="alwaysUseFullPath" value="true"></property>
</bean>
Related
I have this in web.xml:
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Dispatching handled by StaticFilter -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
I have this in dispatcher-servlet.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:annotation-config/>
<!-- Activates scanning of #Repository -->
<context:component-scan base-package="com.pronto.mexp" />
<!-- View Resolver for JSPs -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="requestContextAttribute" value="rc"/>
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
I have this in AlertsController:
#Controller
public class AlertsController {
protected final Log logger = LogFactory.getLog(getClass());
#Autowired
private AlertManager alertManager;
#RequestMapping("/alerts")
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// display in view
logger.info("Returning alerts view");
List<Alert> alerts = alertManager.getAlerts();
request.setAttribute("alerts", alerts);
return new ModelAndView();
}
public void setAlertManager(AlertManager alertManager) {
this.alertManager = alertManager;
}
}
And I have this in alerts.jsp:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<h3>ALERTS</h3>
<table border="1">
<c:forEach var="alert" items="${alerts}">
<tr>
<td>${alert.hostname}</td>
<td>${alert.message}</td>
<td>${alert.program}</td>
<td><fmt:formatDate value="${alert.date}" dateStyle="medium"/></td>
</tr>
</c:forEach>
</table>
But when I start the app up and point my browser to localhost:8080/alerts.jsp, I get only the header "ALERTS" and nothing else. It's like Spring doesn't know to use the AlertsController. I know I'm leaving out some key config but I can't see it.
You're doing it opposite of what you're supposed to. It's not the JSP that knows which controller to use, but the Controller knows which view (JSP) to render. The controller is executed by it's url mapping, which is defined in the #RequestMapping attribute. When you access your JSP directly like that, you're not going through Spring at all. So try using the url http://localhost:8080/context/alerts instead, replacing context with the context path of the web application.
One line Answer : you are calling it in wrong way you have to call /alerts not alerts.jsp
but why you are getting this empty page, because you are calling jsp direct without setting values by controller, you are putting Jsp files under root
<property name="prefix" value="/"/>
so that it is accessible it is better to put it in WEB-INF to prevent direct access
<property name="prefix" value="/WEB-INF/jsps/"/>
My coworker pointed out my dispatcher-servlet.xml was also missing the mvc instruction to scan for annotations in my Controllers:
<!-- Configures the #Controller programming model -->
<mvc:annotation-driven/>
So even when I pointed my browser at localhost:8080/alerts (since I have no context path configured), it was still failing. Once I added the mvc instruction, the controller was invoked, and the dynamic content was sent to the jsp.
I am trying to add open-session-in-view behavior to an existing pure JPA application. Using Spring in the service-tier is not an option. I would like to wrap the view in Spring's OpenEntityManagerInViewFilter, and not have to modify the EJB layer.
I am not having any luck getting OpenEntityManagerInViewFilter (Spring 3.2.2) to work in JBoss 6.1. The filter is definitely being invoked, but I am still getting a LazyInitializationException in the view.
The filter and the session-bean are using a different instance (and class) of the EntityManager. The filter is getting a org.hibernate.ejb.EntityManagerImpl, while the session-bean is getting a org.jboss.jpa.tx.TransactionScopedEntityManager. I am not sure what Spring configuration is responsible for this.
Here is the relevant code/config:
war/WEB-INF/classes/test.web.servlet.TestServlet
public class TestServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
#EJB
private ServiceLocal service;
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
long parentId = Long.parseLong(req.getParameter("parentId"));
Parent parent = service.retrieveParent(parentId);
// this call throws a LazyInitializationException
// because parent.children.session is NULL
parent.getChildren().iterator().next().getName();
req.setAttribute("parent", parent);
RequestDispatcher requestDispatcher = this.getServletContext().getRequestDispatcher("/WEB-INF/jsp/view.jsp");
requestDispatcher.forward(req, resp);
}
}
ejb/test.ejb.session.ServiceBean
#Stateless
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public class ServiceBean implements ServiceLocal, Service {
#PersistenceContext(name="test")
private EntityManager entityManager;
#Override
public Parent retrieveParent(Long parentId) {
return entityManager.find(Parent.class, parentId);
}
}
war/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>test-war</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring.xml</param-value>
</context-param>
<filter>
<filter-name>osiv-filter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
<init-param>
<param-name>flushMode</param-name>
<param-value>AUTO</param-value>
</init-param>
</filter>
<servlet>
<servlet-name>test-servlet</servlet-name>
<servlet-class>test.web.servlet.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test-servlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<filter-mapping>
<filter-name>osiv-filter</filter-name>
<servlet-name>test-servlet</servlet-name>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
</web-app>
war/WEB-INF/spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="persistenceUnitName" value="test" />
<property name="jpaProperties">
<props>
<prop key="hibernate.transaction.manager_lookup_class">
org.hibernate.transaction.JBossTransactionManagerLookup
</prop>
</props>
</property>
</bean>
</beans>
ejb/META-INF/persistence.xml
<persistence
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
<persistence-unit name="test" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/MSSQLDS</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/>
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.use_sql_comments" value="true" />
<property name="jboss.entity.manager.factory.jndi.name" value="java:/testEntityManagerFactory" />
<property name="jboss.entity.manager.jndi.name" value="java:/testEntityManager" />
</properties>
</persistence-unit>
</persistence>
I don't think it's necessary to use a custom EntityManagerFactory to lookup the EntityManagerFactory via JDNI, the element should take care of that.
I have given your setup a little bit more thought and i don't think that the spring OpenEntityManagerInViewFilter will work for you. It binds an entity manager to the current thread so that spring's transaction management code can reuse it. The problem is that spring doesn't handle the transaction management of your service bean as this is handled by the the application server. The application server doesn't detect the entity manager bound to the thread by spring and creates another one; resulting in 2 different instances.
To make it work you should either define your service bean(s) in spring so that spring handles the transaction management or use jboss seam (JBoss Seam: How to Open jpa/hibernate session in view)
If you are sure that the open session in view filter is working then you might want to take a look at the transaction demarcation for service.retrieveParent(parentId);. The LazyInitializationException would make sense if the service/dao uses a different persistence context to load the parent entity.
I am not familiar with the spring/jboss setup and therefore missed some things.
I assume that your service bean is managed by the JBoss server and not by spring. By defining the LocalContainerEntityManagerFactoryBean you are actually configuring an EntityManagerFactory in Spring (very similar to the one managed by the application server). The open session in view filter is injected with the an EntityManager that's managed by Spring while it should have been injected by an entity manager managed by the application server.
I think that the following spring configuration will fix your problem (don't forget to adjust the jndi-name attribute):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">
<context:annotation-config/>
<jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence-units/test"/>
<tx:jta-transaction-manager/>
LazyInitializationException means that hibernate tried to get the data of a lazy collection/object but the session was already closed.
If this line parent.getChildren().iterator().next().getName(); is throwing the error, it means that childrens is a lazy collection with actually no useful data, and by calling iterator().next() hibernate tried to load the entire collection.
I have developed a REST web application with Spring MVC and I can send JSON objects to a client.
I would like to construct a Javascript/AJAX client that connects to my web application but I don't know how to send the first HTML page (using JSP).
I understand I should serve JSP pages with some embedded AJAX. This AJAX will send requests to my web services.
Update:
The requirement I am not able to achieve is to write the default URI (http://localhost:8084) in browser and see the HTML page I have written in JSP page (home.jsp).
My approach is following:
I have a Controller that sends the root JSP page
#Controller
public class SessionController {
#RequestMapping(value="/", method=RequestMethod.GET)
public String homeScreen(){
return "home";
}
}
But when I run the server I receive this warning
WARNING: No mapping found for HTTP request with URI [/home] in DispatcherServlet with name 'dispatcher'
and nothing is loaded in browser.
Here is my application-context file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:component-scan base-package="com.powerelectronics.freesun.web" />
<mvc:annotation-driven />
</beans>
And web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>
Is my approach correct? Am I wrong at any basic concept?
Can I modify something in my code to make it run?
I would like to see the first page loaded in browser and keep going in that direction.
Thanks in advance.
Try adding a #ResponseBody annotation on the method:
#Controller
public class SessionController {
#RequestMapping(value="/", method=RequestMethod.GET)
#ResponseBody
public String homeScreen(){
return "home";
}
}
This should output home on the page.
If you'd like to use View technologies, e.g. JSP, review the following chapter on the official Spring Framework documentation: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#view
Update
"Just as with any other view technology you're integrating with Spring, for JSPs you'll need a view resolver that will resolve your views ". If you'd like to use JSP you should then add the following to your Web application context, then return the name of the file that shall be processed:
<!-- the ResourceBundleViewResolver -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="basename" value="views"/>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
Is the above present in your Web application context? You can review the official documentation for further information: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#view-jsp-resolver
Place a welcome file tag in web.xml file.
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
You must be having this index.jsp outside of WEB-INF. Put following code in it.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<%
response.sendRedirect("home");
%>
</body>
</html>
When application is loaded, it will call index.jsp and jsp will redirect it to /home action.
Then your controller will get called.
#Controller
public class SessionController {
// see the request mapping value attribute here, it is /home
#RequestMapping(value="/home", method=RequestMethod.GET)
public String homeScreen(){
return "home";
}
}
This will call your home jsp.
If you want to to return JSON from your spring controller, then you need jackson mapper bean initialized in spring context xml file.
<beans:bean id="jacksonMessageChanger" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<beans:property name="supportedMediaTypes" value="application/json" />
</beans:bean>
<beans:bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<beans:property name="messageConverters">
<util:list id="beanList">
<beans:ref bean="jacksonMessageChanger" />
</util:list>
</beans:property>
</beans:bean>
You need to add jar or maven dependency to use jackson mapper.
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.8.5</version>
</dependency>
And to return JSON from controller, method would be like this :
#RequestMapping(value="/getContacts", method=RequestMethod.GET)
public #ResponseBody List<Contacts> getContacts(){
List<Contacts> contactList = prepareContactList();
return contactList;
}
This way you will get List in the success function of ajax call in the form of object and by iterating it you can get the details.
Finally I solve this only with configuring the dispatcher in web.xml on a different way.
First I added the view resolver to the servlet configuration file as David Riccitelli suggested me:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/" p:suffix=".jsp"/>
And then I configured the servlet mapping in web.xml:
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
That's what I was looking for, and no extra configuration is needed.
Doing this I call my root URL http://localhost:8084 and I can see the home screen I have coded in home.jsp.
Thanks for your support and suggestions.
I would like to collect all css/js resources in a controller.
This would result in one HTTP Request for each resource.
Example:
package my.package;
// [...imports...]
#Controller
#RequestMapping( "/res" )
public class ResourcesController
{
#RequestMapping( value = "/style.css", headers = "content-type=text/css" )
// [...] collect all css files from /WEB-INF/css/**
#RequestMapping( value = "/scripts.js", headers = "content-type=text/javascript" )
// [...] collect all js files from /WEB-INF/js/**
}
I already have an DispatcherServlet which uses Apache Tiles, so I guess i need to make a new servlet?!
<servlet>
<servlet-name>resources</servlet-name>
<servlet-class>?org.springframework.web.servlet.ResourceServlet?</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>resources</servlet-name>
<url-pattern>/res/*.css</url-pattern>
<url-pattern>/res/*.js</url-pattern>
</servlet-mapping>
Is class org.springframework.web.servlet.ResourceServlet correct?
What I have to put in my resources-servlet.xml then? This?
<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver" />
<context:component-scan base-package="my.package" />
</beans>
And how my mapping methods should look like in the controller?
Any example code would be very useful. Can't find anything on the internet...
I already have an DispatcherServlet which uses Apache Tiles, so I guess I need to make a new servlet?!
No -- you should have only the DispatcherServlet. -- Every Spring Controller is handled by this servlet.
But in general it looks strange what you do.
Spring already have a "tool" that allows to access static ressources ResourceHttpRequestHandler See Spring Reference Chapter 16.14.5 Configuring Serving of Resources
for example
<mvc:resources location="/, classpath:/META-INF/web-resources/"
mapping="/resources/**" />
But maybe you try something more complex like Jawr?
I'm trying to do one of those standard spring mvc hello world applications but with the twist that I'd like to map the controller to the root. (for example: http://numberformat.wordpress.com/2009/09/02/hello-world-spring-mvc-with-annotations/ )
So the only real difference is that they map it to host\appname\something and I'd like to map it to host\appname.
I placed my index.jsp in src\main\webapp\jsp and mapped it in the web.xml as the welcome file.
I tried:
#Controller("loginController")
public class LoginController{
#RequestMapping("/")
public String homepage2(ModelMap model, HttpServletRequest request, HttpServletResponse response){
System.out.println("blablabla2");
model.addAttribute("sigh", "lesigh");
return "index";
}
As my controller but I see nothing appear in the console of my tomcat.
Does anyone know where I'm messing up?
My web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!-- Index -->
<welcome-file-list>
<welcome-file>/jsp/index.jsp</welcome-file>
</welcome-file-list>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
<servlet>
<servlet-name>springweb</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springweb</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
The mvc-dispatcher-servlet.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"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
<context:component-scan base-package="de.claude.test.*" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
I'm using Spring 3.0.5.release
Or is this not possible and do I need to put my index.jsp back in the root of the web-inf and put a redirect to somewhere inside my jsp so the controller picks it up?
I had the same problem, even after following Sinhue's setup, but I solved it.
The problem was that that something (Tomcat?) was forwarding from "/" to "/index.jsp" when I had the file index.jsp in my WebContent directory. When I removed that, the request did not get forwarded anymore.
What I did to diagnose the problem was to make a catch-all request handler and printed the servlet path to the console. This showed me that even though the request I was making was for http://localhost/myapp/, the servlet path was being changed to "/index.html". I was expecting it to be "/".
#RequestMapping("*")
public String hello(HttpServletRequest request) {
System.out.println(request.getServletPath());
return "hello";
}
So in summary, the steps you need to follow are:
In your servlet-mapping use <url-pattern>/</url-pattern>
In your controller use RequestMapping("/")
Get rid of welcome-file-list in web.xml
Don't have any files sitting in WebContent that would be considered default pages (index.html, index.jsp, default.html, etc)
Hope this helps.
The redirect is one option. One thing you can try is to create a very simple index page that you place at the root of the WAR which does nothing else but redirecting to your controller like
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:redirect url="/welcome.html"/>
Then you map your controller with that URL with something like
#Controller("loginController")
#RequestMapping(value = "/welcome.html")
public class LoginController{
...
}
Finally, in web.xml, to have your (new) index JSP accessible, declare
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
We can simply map a Controller method for the default view. For eg, we have a index.html as the default page.
#RequestMapping(value = "/", method = GET)
public String index() {
return "index";
}
once done we can access the page with default application context.
E.g http://localhost:8080/myapp
It works for me, but some differences:
I have no welcome-file-list in web.xml
I have no #RequestMapping at class level.
And at method level, just #RequestMapping("/")
I know these are no great differences, but I'm pretty sure (I'm not at work now) this is my configuration and it works with Spring MVC 3.0.5.
One more thing. You don't show your dispatcher configuration in web.xml, but maybe you have some preffix. It has to be something like this:
<servlet-mapping>
<servlet-name>myServletName</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
If this is not your case, you'll need an url-rewrite filter or try the redirect solution.
EDIT: Answering your question, my view resolver configuration is a little different too:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
It can be solved in more simple way:
in web.xml
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>
After that use any controllers that your want to process index.htm with #RequestMapping("index.htm"). Or just use index controller
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="index.htm">indexController</prop>
</props>
</property>
<bean name="indexController" class="org.springframework.web.servlet.mvc.ParameterizableViewController"
p:viewName="index" />
</bean>
Just put one more entry in your spring xml file i.e.mvc-dispatcher-servlet.xml
<mvc:view-controller path="/" view-name="index"/>
After putting this to your xml put your default view or jsp file in your custom JSP folder as you have mentioned in mvc-dispatcher-servlet.xml file.
change index with your jsp name.
One way to achieve it, is by map your welcome-file to your controller request path in the web.xml file:
[web.xml]
<web-app ...
<!-- Index -->
<welcome-file-list>
<welcome-file>home</welcome-file>
</welcome-file-list>
</web-app>
[LoginController.java]
#Controller("loginController")
public class LoginController{
#RequestMapping("/home")
public String homepage2(ModelMap model, HttpServletRequest request, HttpServletResponse response){
System.out.println("blablabla2");
model.addAttribute("sigh", "lesigh");
return "index";
}
The solution I use in my SpringMVC webapps is to create a simple DefaultController class like the following: -
#Controller
public class DefaultController {
private final String redirect;
public DefaultController(String redirect) {
this.redirect = redirect;
}
#RequestMapping(value = "/")
public ModelAndView redirectToMainPage() {
return new ModelAndView("redirect:/" + redirect);
}
}
The redirect can be injected in using the following spring configuration: -
<bean class="com.adoreboard.farfisa.controller.DefaultController">
<constructor-arg name="redirect" value="${default.redirect:loginController}"/>
</bean>
The ${default.redirect:loginController} will default to loginController but can be changed by inserting default.redirect=something_else into a spring properties file / setting an environment variable etc.
As #Mike has mentioned above I have also: -
Got rid of <welcome-file-list> ... </welcome-file-list> section in the web.xml file.
Don't have any files sitting in WebContent that would be considered default pages (index.html, index.jsp, default.html, etc)
This solution lets Spring worry more about redirects which may or may not be what you like.