0

I'm trying to separate my application core services from my dispatcherservlet and classes that have @Controller annotation. I've read numerous topic here on SO but didn't find any example that suits my case, only explanations about root-child hierarchy, component scan packages and so on.

As all the suggestions tell that in appicationContext.xml I should scan all components except @Controller classes and in my DispatcherServlet-servlet.xml I should scan ONLY for @Controller classes. I did it just like in this @Service are constructed twice example.

So my application builds successfully, but when i go to it's webpage, in Chrome it tells me that This link appears to be broken. This means that the page exists, otherwise Tomcat would tell me that this The requested resource (/myapp) is not available.

There must be something wrong in my configurations. What may be the problem? Here is my applicationContext.xml

<beans <!-- omitting namespaces for readability --> >

    <!-- Scans within the base package of the application for @Components to configure as beans -->
    <!-- @Controller, @Service, @Configuration, etc. -->
    <context:component-scan base-package="com.myapp">
        <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>

    <!-- Enables the Spring MVC @Controller programming model -->
    <mvc:annotation-driven />
    <mvc:resources mapping="/static/**" location="/" />
    <mvc:default-servlet-handler />
    <jpa:repositories base-package="com.myapp.repo" />
</beans>

Next is my web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app <!-- omitting namespaces for readability -->>

  <display-name>My application</display-name>

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        classpath:applicationContext.xml
        classpath:spring-security.xml
        </param-value>
  </context-param>

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

  <listener>
    <listener-class>
        org.springframework.web.context.request.RequestContextListener
    </listener-class>
  </listener>

  <servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>DispatcherServlet</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>

    <!-- Ensure UTF-8 encoded pages so that certain characters are displayed and submitted correctly -->
    <filter>
        <filter-name>encodingFilter</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>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- Enables support for DELETE and PUT request methods with web browser clients -->
    <filter>
        <filter-name>hiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>hiddenHttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <error-page>
        <error-code>404</error-code>
        <location>/WEB-INF/view/error/404.jsp</location>
    </error-page>
</web-app>

Below is DispatcherServlet-servlet.xml

<beans <!-- omitting namespaces for readability -->>
    <context:component-scan base-package="com.myapp.mvc" use-default-filters="false">
        <context:include-filter type="annotation"
            expression="org.springframework.stereotype.Controller" />
    </context:component-scan>
</beans>

Here is my configuration class

@Configuration
@ImportResource("classpath:applicationContext.xml")
@PropertySource("classpath:images.properties")
public class AppConfig implements InitializingBean {

    @Inject
    ServletContext context;

    // Resolve logical view names to .jsp resources in the /WEB-INF/views directory
    @Bean
    ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("WEB-INF/view/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

    // Configure the multipart resolver
    @Bean
    CommonsMultipartResolver multipartResolver() {
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
//      multipartResolver.setMaxUploadSize(2_202_009);
        return multipartResolver;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        File logoImgPreview = new File("resources/img/image_footer_logo_preview.jpg");
        BufferedImage bufImgPreview = ImageIO.read(logoImgPreview);
        context.setAttribute("watermark_preview", bufImgPreview);
    }
}

So and lastly here is the log when my server starts:

http://pastie.org/private/z8zv7jaddytxsgbh7oggw

What I see in the server logs that DispatcherServlet defines the controller beans but applicationContext maps RequestMappingHandlers. Should it be like so? I'm not really sure about the whole picture how everything should work, but according to everything I've read till now, this kind of context separating must be correct. But then where are the mistakes in my configurations?

Here is my homecontroller which is very basic

@Controller
public class HomeController {

    private static Logger log = LoggerFactory.getLogger("com.myapp.mvc.HomeController");

    @RequestMapping("/")
    public String home() {
        log.debug("Requesting index page");
        return "index"; // it returns to index.jsp
    }
}
Community
  • 1
  • 1
Skyzer
  • 584
  • 3
  • 11
  • 27

1 Answers1

3

You should move all the controller related bean definitions to the Dispatcher-servlet.xml file, you still have some in the applicationContext.xml file -

<mvc:annotation-driven />
<mvc:resources mapping="/static/**" location="/" />
<mvc:default-servlet-handler />

This may not be all the reasons for the issues you are seeing but should take you a little further.

Biju Kunjummen
  • 49,138
  • 14
  • 112
  • 125