1

I had a Spring MVC project that was using XML for all the config stuff but I remove all the XML and made them into JavaConfig (Everything but Spring Security). Once I try to get Spring Security working I could see that my project was blowing up looking for applicationContext.xml in WEB.INF. I dont have anything pointing to that so who do I need it>?

my secuirty.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="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-3.1.xsd
                        http://www.springframework.org/schema/security
                        http://www.springframework.org/schema/security/spring-security-3.1.xsd">


    <global-method-security pre-post-annotations="enabled" />

    <http use-expressions="true">
        <intercept-url access="hasRole('ROLE_VERIFIED_MEMBER')" pattern="/mrequest**" />
        <intercept-url pattern='/*' access='permitAll' />
        <form-login default-target-url="/visit" />

        <logout logout-success-url="/" />
    </http>

    <authentication-manager>
        <authentication-provider>
            <user-service>
                <user name="cpilling04@aol.com.dev" password="testing" authorities="ROLE_VERIFIED_MEMBER" />
            </user-service>

        </authentication-provider>
    </authentication-manager>
</beans:beans>

Here is my webconfig:

@Configuration
@EnableWebMvc
@Import(DatabaseConfig.class)
@ImportResource("/WEB-INF/spring/secuirty.xml")
public class WebMVCConfig extends WebMvcConfigurerAdapter {

    private static final String MESSAGE_SOURCE = "/WEB-INF/classes/messages";

    private static final Logger logger = LoggerFactory.getLogger(WebMVCConfig.class);



    @Bean
    public  ViewResolver resolver() {
        UrlBasedViewResolver url = new UrlBasedViewResolver();
        url.setPrefix("/WEB-INF/view/");
        url.setViewClass(JstlView.class);
        url.setSuffix(".jsp");
        return url;
    }


    @Bean(name = "messageSource")
    public MessageSource configureMessageSource() {
        logger.debug("setting up message source");
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename(MESSAGE_SOURCE);
        messageSource.setCacheSeconds(5);
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }

    @Bean
    public LocaleResolver localeResolver() {
        SessionLocaleResolver lr = new SessionLocaleResolver();
        lr.setDefaultLocale(Locale.ENGLISH);
        return lr;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        logger.debug("setting up resource handlers");
        registry.addResourceHandler("/resources/").addResourceLocations("/resources/**");
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        logger.debug("configureDefaultServletHandling");
        configurer.enable();
    }

    @Override
    public void addInterceptors(final InterceptorRegistry registry) {
        registry.addInterceptor(new LocaleChangeInterceptor());
    }

    @Bean
    public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {
        SimpleMappingExceptionResolver b = new SimpleMappingExceptionResolver();

        Properties mappings = new Properties();
        mappings.put("org.springframework.web.servlet.PageNotFound", "p404");
        mappings.put("org.springframework.dao.DataAccessException", "dataAccessFailure");
        mappings.put("org.springframework.transaction.TransactionException", "dataAccessFailure");
        b.setExceptionMappings(mappings);
        return b;
    }

    @Bean
    public RequestTrackerConfig requestTrackerConfig()
    {
        RequestTrackerConfig tr = new RequestTrackerConfig();
        tr.setPassword("Waiting#$");
        tr.setUrl("https://uftwfrt01-dev.uftmasterad.org/REST/1.0");
        tr.setUser("root");

        return tr;
    }


}

Here is my DatabaseConfig:

@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages= "org.uftwf")
@PropertySource(value = "classpath:application.properties")
public class DatabaseConfig  {


    private static final Logger logger = LoggerFactory.getLogger(DatabaseConfig.class);


    @Value("${jdbc.driverClassName}")
    private String driverClassName;

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    @Value("${hibernate.dialect}")
    private String hibernateDialect;

    @Value("${hibernate.show_sql}")
    private String hibernateShowSql;

    @Value("${hibernate.hbm2ddl.auto}")
    private String hibernateHbm2ddlAuto;

    @Bean
    public PropertyPlaceholderConfigurer getPropertyPlaceholderConfigurer()
    {
        PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
        ppc.setLocation(new ClassPathResource("application.properties"));
        ppc.setIgnoreUnresolvablePlaceholders(true);
        return ppc;
    }



    @Bean
     public DataSource dataSource()  {

        try {
            Context ctx = new InitialContext();
            return (DataSource) ctx.lookup("java:jboss/datasources/mySQLDB");
        }
        catch (Exception e)
        {

        }

        return null;
     }

    @Bean
    public SessionFactory sessionFactory()
    {

        LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
        factoryBean.setDataSource(dataSource());
        factoryBean.setHibernateProperties(getHibernateProperties());
        factoryBean.setPackagesToScan("org.uftwf.inquiry.model");

        try {
            factoryBean.afterPropertiesSet();
        } catch (IOException e) {
            logger.error(e.getMessage());
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }


        return factoryBean.getObject();
    }

    @Bean
    public Properties getHibernateProperties()
    {
        Properties hibernateProperties = new Properties();

        hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
        hibernateProperties.setProperty("hibernate.show_sql", "true");

        hibernateProperties.setProperty("hibernate.format_sql", "true");
        hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "update");

        hibernateProperties.setProperty("javax.persistence.validation.mode", "none");

        //Audit History flags
        hibernateProperties.setProperty("org.hibernate.envers.store_data_at_delete", "true");
        hibernateProperties.setProperty("org.hibernate.envers.global_with_modified_flag", "true");

        return hibernateProperties;
    }



    @Bean
    public HibernateTransactionManager hibernateTransactionManager()
    {
        HibernateTransactionManager htm = new HibernateTransactionManager();
        htm.setSessionFactory(sessionFactory());
        htm.afterPropertiesSet();
        return htm;
    }


}

and 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"
         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>Inquiry</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <servlet>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
        </init-param>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>org.uftwf.inquiry.config, org.uftwf.inquiry.controller</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>





 <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>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!--


 <security-constraint>
     <web-resource-collection>
         <web-resource-name>securedapp</web-resource-name>
         <url-pattern>/*</url-pattern>
     </web-resource-collection>

     <user-data-constraint>
         <transport-guarantee>CONFIDENTIAL</transport-guarantee>
     </user-data-constraint>
 </security-constraint>
-->
</web-app>

So I dont see anything looking for applicationContext.xml .... can someone please tell me why I need it to add it and once I did it started to work

SJS
  • 5,607
  • 19
  • 78
  • 105

3 Answers3

4

You configured ContextLoaderListener in your web.xml, but haven't specified the contextConfigLocation context-param. The behaviour in this case is described by the javadoc of that class:

Processes a "contextConfigLocation" context-param [...] If not explicitly specified, the context implementation is supposed to use a default location (with XmlWebApplicationContext: "/WEB-INF/applicationContext.xml").

So, it is the ContextLoaderListener that requires a applicationContext.xml.

zagyi
  • 17,223
  • 4
  • 51
  • 48
  • but why is it looking for it once I add the "@ImportResource" – SJS Mar 18 '13 at 14:17
  • 1
    You didn't let the `ContextLoaderListener` know where your Spring config class is, so how do you expect it to magically know about that annotation? Read the [javadoc](http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/context/ContextLoader.html), and include a `contextClass` context-param (pointing to your config class) in your web.xml accordingly. – zagyi Mar 18 '13 at 14:42
  • Also it feels like you need a refresher on what is the root web application context (set up by the `ContextLoaderListener`), and the servlet application context (created by the `DispatcherServlet`), and what is the relationship between them. See [this post](http://stackoverflow.com/q/3652090/1276804) for some quick clarification. – zagyi Mar 18 '13 at 14:52
4

Spring Application contexts are hierarchical. The typical arrangement in a web app is that the context loader listener bootstraps your AC and makes them available 'globally', then each individual DispatcherServlet will have its own child application context that can 'see' all the beans (typically services, data sources, etc.) from the context loader listener's AC. In all cases - when specifying the ContextLoaderListener or the DispatcherServlet - Spring will automatically (based on convention) look for an XML application context and attempt to load it. Usually you can disable this by simply specifying an empty contextConfigLocation param ("") or by telling it that it should expect a Java config class, instead (contextClass attribute). BTW, it is possible to have multiple DispatcherServlets. You might, for example, use Spring Integration's inbound HTTP adapter with one, a Spring Web Services endpoint with another, Spring MVC app on another and a Spring HTTP invoker endpoint on another still, and they'd all be exposed via a DispatcherServlet. You could, theoretically, make them all work in the same DispatcherServlet, but the isolation helps keep things less cluttered and they can all share the same single instances of global, more expensive beans, like DataSources.

Josh Long
  • 2,010
  • 17
  • 12
  • I have added an answer below to help show have you can disable Spring from looking for an xml. – LanceP Dec 01 '16 at 01:42
0

To make sure your app doesn't use applicationContext.xml you can do something similar to this. You can see how this all goes together here.

public class MyInitializer implements WebApplicationInitializer {

@Override
public void onStartup(ServletContext servletContext) {

    //Clear out reference to applicationContext.xml
    servletContext.setInitParameter("contextConfigLocation", "");

    // Create the 'root' Spring application context
    AnnotationConfigWebApplicationContext rootContext =
            new AnnotationConfigWebApplicationContext();
    rootContext.register(MySpringRootConfiguration.class);

    // Manage the lifecycle of the root application context
    servletContext.addListener(new ContextLoaderListener(rootContext));

    //Add jersey or any other servlets
    ServletContainer jerseyServlet = new ServletContainer(new RestApplication());
    Dynamic servlet = servletContext.addServlet("jersey-servlet", jerseyServlet);
    servlet.addMapping("/api/*");
    servlet.setLoadOnStartup(1);
}
}
LanceP
  • 974
  • 1
  • 9
  • 15