Why my applicationContext.xml is needed by DispatcherServlet? - spring

isn't DispatcherServlet is responsible for managing the mvc-config only, and the ContextLoaderListener is responsible for applicationContext.xml
this was my old configuration for web.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<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_2_5.xsd" version="2.5">
<!-- start up and shut down Spring's root WebApplicationContext (Interface to provide configuration for a web application) -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Central dispatcher for HTTP request handlers/controllers: take an incoming URI and find the right combination of handlers (generally methods on Controller classes)
and views (generally JSPs) that combine to form the page or resource that's supposed to be found at that location. -->
<servlet>
<servlet-name>p</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/webmvc-config.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>p</servlet-name>
<url-pattern>/p/*</url-pattern>
</servlet-mapping>
<!-- allows one to specify a character encoding for requests.
This is useful because current browsers typically do not set a character encoding even if specified in the HTML page or form -->
<filter>
<filter-name>encoding-filter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding-filter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/applicationContext.xml
</param-value>
</context-param>
<!--
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
-->
<!-- Based on the popular and very useful mod_rewrite for apache, UrlRewriteFilter is a Java Web Filter for any J2EE
compliant web application server (such as Resin or Tomcat), which allows you to rewrite URLs before they get to your
code. It is a very powerful tool just like Apache's mod_rewrite. -->
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
but with this config, i got the following exception:
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:574)
com.spring.sample.dao.impl.PersonDaoImpl.getCurrentSession(PersonDaoImpl.java:30)
com.spring.sample.dao.impl.PersonDaoImpl.getAllPersons(PersonDaoImpl.java:69)
com.spring.sample.controller.PersonsController.get(PersonsController.java:34)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doInvokeMethod(HandlerMethodInvoker.java:710)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:167)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:414)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:402)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:771)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:716)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:647)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:552)
javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:70)
org.tuckey.web.filters.urlrewrite.NormalRewrittenUrl.doRewrite(NormalRewrittenUrl.java:195)
org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:159)
org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:141)
org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:90)
org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:417)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
webmvc-config.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:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
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/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- webmvc-config.xml: is for web configuration, and it's loaded with Dispatacher Servlet -->
<context:component-scan base-package="com.spring.sample" />
<!-- - It declares explicit support for annotation-driven MVC controllers (i.e. #RequestMapping, #Controller, etc).
- configures support for new Spring MVC features such as declarative validation with #Valid, HTTP message conversion with #RequestBody/#ResponseBody.
- supports Spring Jackson JSON. -->
<mvc:annotation-driven />
<!-- Changes the locale when a 'lang' request parameter is sent; e.g. /?lang=ar -->
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"
p:paramName="lang" />
</mvc:interceptors>
<!-- uses a locale attribute in the user's session -->
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.SessionLocaleResolver" />
<!-- - translates from view name to view class.
- makes views avaiable to controllers, when controller return a view name, the view name is rendered. -->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
<!-- viewResolver for jsp -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
but this exception was solved after adding applicationContext.xml to DispatcherServlet in my web.xml, any ideas why ?

I guess you use #Transactional. If so, note that the effect of <tx:annotation-driven /> is limited to the context where it is declared.
So, if you have any beans with #Transactional declared in webmvc-config.xml, you should also add <tx:annotation-driven /> there. If <tx:annotation-driven /> is specified in applicationContext.xml only, it can result in behaviour you describe.

I think it has to do with each dispatch servlet having it's own context, look at this blog
http://www.dotkam.com/2008/07/09/spring-web-application-context-visibility/
I solved this problem by doing some thing like this, I use listener to load all my context files like this
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/applicationContext.xml, /WEB-INF/spring/applicationContext-MVC.xml
</param-value>
</context-param>
I created a dummy context config with no configuration defined in it, I had to do this since dispatch servlet complains of not having context configuration
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/dummy-config.xml
</param-value>
</init-param>

Related

Spring DispatcherServlet context instantiation error in liferay 6.1.1

I'm in the process of migrating the liferay version of my webapp from 6.1.0 to 6.1.1 (using the 6.1.1-ga2 version from liferay patchers community and have a little problem with my webservices that where previously working.
I use the PortalDelegateServlet to instantiate a spring DispatcherServlet.
The problem I have is that the spring context of my servlet (myWS-servlet.xml) is instantiate before the application context of the PortletContextLoaderListener ( also tried with the ContextLoaderListener from spring, same problem )
and, as my controllers use services from the principal application context (which is not loaded at the time the DispatcherServlet is instantiated), spring cannot autowired them.
Strange thing is that the problem is resolved if I redeploy my portlet.
Do you have any idea how I can fix this ?
my 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_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>banner-portlet</display-name>
<jsp-config>
<taglib>
<taglib-uri>http://java.sun.com/portlet_2_0</taglib-uri>
<taglib-location>/WEB-INF/tlds/liferay-portlet.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>http://liferay.com/tld/theme</taglib-uri>
<taglib-location>/WEB-INF/tlds/liferay-theme.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>http://liferay.com/tld/portlet</taglib-uri>
<taglib-location>/WEB-INF/tlds/liferay-portlet-ext.tld</taglib-location>
</taglib>
</jsp-config>
<servlet>
<servlet-name>liferayWSdispatcher</servlet-name>
<servlet-class>com.liferay.portal.kernel.servlet.PortalDelegateServlet</servlet-class>
<init-param>
<param-name>servlet-class</param-name>
<param-value>org.springframework.web.servlet.DispatcherServlet</param-value>
</init-param>
<init-param>
<param-name>sub-context</param-name>
<param-value>rest-api</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>liferayWSdispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>com.liferay.portal.spring.context.PortletContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<!-- Instruct Mojarra to utilize JBoss-EL instead of the EL implementation
provided by the servlet container. -->
<!-- was used only for admin portlets but make calendar portlet crash
<context-param>
<param-name>com.sun.faces.expressionFactory</param-name>
<param-value>org.jboss.el.ExpressionFactoryImpl</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>
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
<listener>
<listener-class>com.liferay.faces.portal.listener.StartupListener</listener-class>
</listener>
<!-- MyFaces will not initialize unless a servlet-mapping to the Faces Servlet
is present. -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<context-param>
<param-name>portalContextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext-velocity-tool.xml</param-value>
</context-param>
my applicationContext.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: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.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="be.maximede">
<context:exclude-filter type="regex" expression="be.maximede.webservice.*"/>
</context:component-scan>
my myWS-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="be.maximede.webservice"/>
<mvc:annotation-driven />
I know this thread is over a year old. But I wanted to help save people some trouble. My coworkers and I spent a week trying to figure this out why we can't load spring services before portlet controllers using spring and PortalDelegateServlet + DispatcherServlet.
It's somewhat but not directly related to the Issue http://issues.liferay.com/browse/LPS-29103 as the other poster commented. It does have to do with the way Servlets were initialized in liferay and how Liferay handles web.xml rewrite.
Liferay rewrites all your listeners defined within web.xml and puts them into a context param likes this:
<context-param>
<param-name>portalListenerClasses</param-name>
<param-value>com.liferay.portal.kernel.servlet.SerializableSessionAttributeListener,org.springframework.web.context.ContextLoaderListener</param-value>
</context-param>
and then creates its own listener (or not shown, a PluginContextListener):
<listener>
<listener-class>com.liferay.portal.kernel.servlet.SecurePluginContextListener</listener-class>
</listener>
This SecurePluginContextListener then loads up the context and wires things up. The problem is that sometimes, SecurePluginContextListener will initialize PortalDelegateServlet with the Web Application Context first and then it moves on to the init methods within the portalListenerClasses. So any AutoWired stuff within the portlet controller is missing all their dependencies (services from the application context).
In order to get around this, we ditched declaring PortalDelegateServlet within the web.xml and created a custom ServletContextListener that would new up a PortalDelagateServlet and ServletConfig, passing in the same parameters to spring's DispatcherServlet. The reason why this works is because, we let Liferay do all the loading within portalListenerClasses. The rewritten web.xml would look like this:
<context-param>
<param-name>portalListenerClasses</param-name>
<param-value>com.liferay.portal.kernel.servlet.SerializableSessionAttributeListener,org.springframework.web.context.ContextLoaderListener, com.domain.CustomContextListener</param-value>
</context-param>
And CustomContextListener would implement the methods in ServletContextListener.
Within CustomContextListener's contextInitialized(...) method, we just programmatically create the same ServletConfig (An inner class that implements ServletConfig) we had inside the web.xml. We then create a pds = new PortalDelegateServlet() and call pds.init(customServletConfig)
For Liferay 6.1.1 this is a known issue:
http://issues.liferay.com/browse/LPS-29103

How can I use boolean parameters from application.properties in spring security context configuration xml file?

I am trying to use a boolean parameter from my application.properties in my spring-security configuration xml file.
I don't know why I can use not-boolean parameters, but I get an error for boolean.
How can I use boolean parameters?
Here is my application.properties:
JDBC_CONNECTION_STRING=jdbc:mysql://localhost:3306/schema?user=username&password=password
protocol=http
USE_SECURE=false
My spring-security.xml is:
< remember-me user-service-ref="internalUserDetails" data-source-ref="dataSource" key="this-is-my-key02203452416fw" use-secure-cookie="${USE_SECURE}" />
...
but I get this error:
cvc-datatype-valid.1.2.1: '${USE_SECURE}' is not a valid value for 'boolean'
I have also tried to set USE_SECURE=False but I get the same error again.
How can I use boolean parameters in the spring security configuration xml file?
Here is my web.xml:
<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_3_0.xsd"
version="3.0" >
<display-name> Name-MyApp</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- Servlets -->
<servlet>
<servlet-name>MyApp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Servlets Mappings -->
<servlet-mapping>
<servlet-name>MyApp</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/servlet-context.xml,
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<!-- Filters -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>httpMethodFilter</filter-name>
<servlet-name>MyApp</servlet-name>
</filter-mapping>
<filter>
<filter-name>httpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
Looks that instead the value the key '${USE_SECURE}' is being passed. I come across similiar issue when I wanted to inistiate Boolean
<bean id="flag" class="java.lang.Boolean">
<constructor-arg value="${FLAG}"/>
</bean>
It works ok with the 'property', so i solved my case in other way. I am not sure if it is a spring bug?
The xsd schema definition of the security namespace only allows boolean values in the use-secure-cookie attribute. If you don't specify one of the allowed literals ("true" or "false"), your xml won't pass the schema validation, and won't get even parsed.
So if you use the security namespace configuration, you won't be able to use external properties to set this value. To prove my point, here is the relevant code snippet from RememberMeBeanDefinitionParser.parse():
String useSecureCookie = element.getAttribute("use-secure-cookie");
if (StringUtils.hasText(useSecureCookie)) {
services.getPropertyValues().addPropertyValue(
"useSecureCookie", Boolean.valueOf(useSecureCookie));
}
As you can see the attribute is straight away converted to boolean, so no mechanism is given any chance to further process the value.
I'm not completely sure, but chances are that this could be fixed by simply relaxing the xsd to allow any string value, and pass that value to the bean definition (services above) without converting it to boolean. Then a PropertyPlaceholderConfigurer could later resolve the given value if it happens to be a property placeholder.
If you want to give it a try, feel free to open a ticket in the Spring Security issue tracker.

How to change Spring MVC default controller name and it's location

I am new to Java and Spring Framework. Iam using Spring STS 3.1.0.RELEASE with tomcat 7. I creating Spring MVC project by using following directions . File > Spring Template Project > Spring MVC Project. Follwoing is web.xml file code :
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
And following is servlet-contxt.xml file :
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
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">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="org.dave.foo" />
</beans:beans>
I want ot change default name and location of controller. For this purpose, I create new package org.dave.bar and move IndexController to this package. I also make change as mentioned below in servlet-context.xml file :
<context:component-scan base-package="org.dave.bar" />
But I receive 404 error after restaring web server and running the code on this url (http://localhost:8080/bar/). Can some one guied me what Iam doing wrong and how it can be rectified.
Thanks in advance
First in the web.xml you will need to define the URL Mapping for which you want the Spring MVC Dispatcher Servlet to handle(via request mapped methods in the controllers).
From what I understand in your question you will want to set the URL Mapping as follow (in web.xml)
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Second,
Under org.dave.foo you will need to place your Spring MVC controllers (classes annotated with #Controller and the URL mapped methods).
In your controller you will need a method mapped to the root of the spring dispatcher servlet URL mapping (defined in web.xml DispatcherServlet):
So for the definition in above you will need a method like this:
#RequestMapping(value = "/")
public ModelAndView index(HttpServletRequest request,
HttpServletResponse response) {
...
}
Note that in general the most specific requests mapping "wins". This means that if you have a request mapping of "/abc" in a controller in addition to the "/" request mapping, then, a request localhost/myapp/abc will "win" localhost/myapp/
You can take a look at a more detailed example here:
http://www.commonj.com/blogs/2012/11/30/spring-mvc-default-controller-name/
Hope it helped.

#Autowired does not work Spring 3

I looked all around to find a solution and couldn't find.
I am using Tomcat, Spring 3 with the jars:
org.springframework.aop-3.0.5.RELEASE.jar
org.springframework.asm-3.0.5.RELEASE.jar
org.springframework.beans-3.0.5.RELEASE.jar
org.springframework.context-3.0.5.RELEASE.jar
org.springframework.core-3.0.5.RELEASE.jar
org.springframework.expression-3.0.5.RELEASE.jar
org.springframework.jdbc-3.0.5.RELEASE.jar
org.springframework.orm-3.0.5.RELEASE.jar
org.springframework.test-3.0.5.RELEASE.jar
org.springframework.transaction-3.0.5.RELEASE.jar
org.springframework.web-3.0.5.RELEASE.jar
and my code is like this:
public class EmailResource {
#Autowired
EmailManager emailManager;
}
in applicationContext I have:
<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
class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="emailManager" class="com.mycompany.manager.impl.EmailManagerImpl" />
<context:component-scan base-package="com.mycompany.component" />
and the web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
However, the emailManager is always null! What am I missing?
EDITED
The EmailResource is jersey servlet for rest calls and is defined like this:
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.mycompany.resource</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
You need to use a Jersey/Spring connecter to get Jersey to recognize your Spring context on startup.
Replace:
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.mycompany.resource</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
With:
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
....
</init-param>
</servlet>
You'll also need the jersey-spring dependency:
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-spring</artifactId>
<version>${jersey.version}</version>
</dependency>
The problem is that the Jersey servlet is specified in web.xml as a servlet and thus is not under control of Spring. Spring can't wire the dependencies.
I don't know much about Jersey, but I found this article that is maybe useful to you.
Further, you've to consider EmailManager is an instance variable of a Servlet, and you declared it as Spring Singleton (the default):
<bean id="emailManager" class="com.mycompany.manager.impl.EmailManagerImpl" />
Thus emailManager should not have any state or it will be non-thread safe.
To explain the problem: suppose that emailManager contains a state, such as a destination address, a subject and a message body. Since is defined as a Singleton, there is only one instance for the whole application. If the servlet is called at the same time by two different people, it could happen that the first process inserts the subject and that same subject is rewritten by the second process before the first was able to send the email. So the data of the two emails will be mixed.
Alternatively it can be defined with scope request, so each request will have a different instance.

Splitting applicationContext to multiple files

What is the correct way to split Spring's configuration to multiple xml files?
At the moment I have
/WEB-INF/foo-servlet.xml
/WEB-INF/foo-service.xml
/WEB-INF/foo-persistence.xml
My web.xml has the following:
<servlet>
<description>Spring MVC Dispatcher Servlet</description>
<servlet-name>intrafest</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/foo-*.xml
</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/foo-*.xml
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
The actual questions:
Is this approach correct/best?
Do I really need to specify the config locations both in the DispatcherServlet AND the context-param sections?
What do I need to keep in mind to be able to reference beans defined in foo-servlet.xml from foo-service.xml? Does this have something to do with specifying contextConfigLocation in web.xml?
Update 1:
I'm using Spring framework 3.0. It's my understanding that I don't need to do resource importing like this:
<import resource="foo-services.xml"/>
Is this a correct assumption?
I find the following setup the easiest.
Use the default config file loading mechanism of DispatcherServlet:
The framework will, on initialization
of a DispatcherServlet, look for a
file named [servlet-name]-servlet.xml
in the WEB-INF directory of your web
application and create the beans
defined there (overriding the
definitions of any beans defined with
the same name in the global scope).
In your case, simply create a file intrafest-servlet.xml in the WEB-INF dir and don't need to specify anything specific information in web.xml.
In intrafest-servlet.xml file you can use import to compose your XML configuration.
<beans>
<bean id="bean1" class="..."/>
<bean id="bean2" class="..."/>
<import resource="foo-services.xml"/>
<import resource="foo-persistence.xml"/>
</beans>
Note that the Spring team actually prefers to load multiple config files when creating the (Web)ApplicationContext. If you still want to do it this way, I think you don't need to specify both context parameters (context-param) and servlet initialization parameters (init-param). One of the two will do. You can also use commas to specify multiple config locations.
Mike Nereson has this to say on his blog at:
http://blog.codehangover.com/load-multiple-contexts-into-spring/
There are a couple of ways to do this.
1. web.xml contextConfigLocation
Your first option is to load them all into your Web application
context via the ContextConfigLocation element. You’re already going
to have your primary applicationContext here, assuming you’re writing
a web application. All you need to do is put some white space between
the declaration of the next context.
<context-param>
<param-name> contextConfigLocation </param-name>
<param-value>
applicationContext1.xml
applicationContext2.xml
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
The above uses carriage returns. Alternatively, yo could just put in a
space.
<context-param>
<param-name> contextConfigLocation </param-name>
<param-value> applicationContext1.xml applicationContext2.xml </param-value>
</context-param>
<listener>
<listener-class> org.springframework.web.context.ContextLoaderListener </listener-class>
</listener>
2. applicationContext.xml import resource
Your other option is to just add your primary applicationContext.xml
to the web.xml and then use import statements in that primary context.
In applicationContext.xml you might have…
<!-- hibernate configuration and mappings -->
<import resource="applicationContext-hibernate.xml"/>
<!-- ldap -->
<import resource="applicationContext-ldap.xml"/>
<!-- aspects -->
<import resource="applicationContext-aspects.xml"/>
Which strategy should you use?
1. I always prefer to load up via web.xml.
Because , this allows me to keep all contexts isolated from each
other. With tests, we can load just the contexts that we need to run
those tests. This makes development more modular too as components
stay loosely coupled, so that in the future I can extract a package
or vertical layer and move it to its own module.
2. If you are loading contexts into a non-web application, I would use the import resource.
There are two types of contexts we are dealing with:
1: root context (parent context. Typically include all jdbc(ORM, Hibernate) initialisation and other spring security related configuration)
2: individual servlet context (child context.Typically Dispatcher Servlet Context and initialise all beans related to spring-mvc (controllers , URL Mapping etc)).
Here is an example of web.xml which includes multiple application context file
<?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_3_0.xsd">
<display-name>Spring Web Application example</display-name>
<!-- Configurations for the root application context (parent context) -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/jdbc/spring-jdbc.xml <!-- JDBC related context -->
/WEB-INF/spring/security/spring-security-context.xml <!-- Spring Security related context -->
</param-value>
</context-param>
<!-- Configurations for the DispatcherServlet application context (child context) -->
<servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/mvc/spring-mvc-servlet.xml
</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<url-pattern>/admin/*</url-pattern>
</servlet-mapping>
</web-app>
#eljenso : intrafest-servlet.xml webapplication context xml will be used if the application uses SPRING WEB MVC.
Otherwise the #kosoant configuration is fine.
Simple example if you dont use SPRING WEB MVC, but want to utitlize SPRING IOC :
In web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application-context.xml</param-value>
</context-param>
Then, your application-context.xml will contain: <import resource="foo-services.xml"/>
these import statements to load various application context files and put into main application-context.xml.
Thanks and hope this helps.
I'm the author of modular-spring-contexts.
This is a small utility library to allow a more modular organization of spring contexts than is achieved by using Composing XML-based configuration metadata. modular-spring-contexts works by defining modules, which are basically stand alone application contexts and allowing modules to import beans from other modules, which are exported ín their originating module.
The key points then are
control over dependencies between modules
control over which beans are exported and where they are used
reduced possibility of naming collisions of beans
A simple example would look like this:
File moduleDefinitions.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:module="http://www.gitlab.com/SpaceTrucker/modular-spring-contexts"
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.gitlab.com/SpaceTrucker/modular-spring-contexts xsd/modular-spring-contexts.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config />
<module:module id="serverModule">
<module:config location="/serverModule.xml" />
</module:module>
<module:module id="clientModule">
<module:config location="/clientModule.xml" />
<module:requires module="serverModule" />
</module:module>
</beans>
File serverModule.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:module="http://www.gitlab.com/SpaceTrucker/modular-spring-contexts"
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.gitlab.com/SpaceTrucker/modular-spring-contexts xsd/modular-spring-contexts.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config />
<bean id="serverSingleton" class="java.math.BigDecimal" scope="singleton">
<constructor-arg index="0" value="123.45" />
<meta key="exported" value="true"/>
</bean>
</beans>
File clientModule.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:module="http://www.gitlab.com/SpaceTrucker/modular-spring-contexts"
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.gitlab.com/SpaceTrucker/modular-spring-contexts xsd/modular-spring-contexts.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config />
<module:import id="importedSingleton" sourceModule="serverModule" sourceBean="serverSingleton" />
</beans>

Resources