1

We are trying to upgrade from pre-release version of Java DXA to Java DXA 1.4.1. We have 2 custom Page Controllers and the whole setup was working fine with the older release of DXA. However when trying to run the webapp against DXA 1.4.1 we are getting page controller conflict related errors.

In our custom controller we were handling custom actions for 2 main features:

  1. Handling all AJAX requests from the pages

  2. We have some short URLs which are used for online campaigns

Now these 2 custom Page Controllers are creating a conflict with the standard DXA Page Controller.

Note that we are running this on a SDL Tridion 2013 SP1 setup.

package com.sdl.webapp.main.controller;
// import statements

@Controller
public class GenericMainController extends BaseController {

// TODO: Move this to common-impl or core-module

private static final Logger LOG = LoggerFactory.getLogger(GenericMainController.class);

private final UrlPathHelper urlPathHelper = new UrlPathHelper();

private final ContentProvider contentProvider;
private final LinkResolver linkResolver;
private final MediaHelper mediaHelper;
private final WebRequestContext webRequestContext;
private final Markup markup;
private final ViewResolver viewResolver;
private final DataFormatter dataFormatters;

@Value("#{environment.getProperty('AllowJsonResponse', 'false')}")
private boolean allowJsonResponse;
@Autowired
private NavigationProvider navigationProvider;
@Autowired
private ObjectMapper objectMapper;

@Autowired
public GenericMainController(ContentProvider contentProvider, LinkResolver linkResolver, MediaHelper mediaHelper,
                      WebRequestContext webRequestContext, Markup markup, ViewResolver viewResolver, DataFormatter dataFormatter) {
    this.contentProvider = contentProvider;
    this.linkResolver = linkResolver;
    this.mediaHelper = mediaHelper;
    this.webRequestContext = webRequestContext;
    this.markup = markup;
    this.viewResolver = viewResolver;
    this.dataFormatters = dataFormatter;
}
/**
 * Gets a page requested by a client. This is the main handler method which gets called when a client sends a
 * request for a page.
 *
 * @param request The request.
 * @return The view name of the page.
 */
@RequestMapping(method = RequestMethod.GET, value = {"/en/{pageName}", "/ar/{pageName}", "/en/dashboard/{pageName}"}, produces = {MediaType.TEXT_HTML_VALUE, MediaType.ALL_VALUE})
public String handleGetPage(@PathVariable Map<String, String> pathVariables, HttpServletRequest request, HttpServletResponse response) {
    .......
}
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'campaignRedirectsController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping com.sdl.webapp.common.controller.BaseController.requestMappingHandlerMapping; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'pageController' bean method 
public java.lang.String com.sdl.webapp.common.controller.BaseController.handleJspIncludesErrors()
to {[/system/mvc/Shared/Error/SectionError],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'campaignRedirectsController' bean method
public java.lang.String com.sdl.webapp.common.controller.BaseController.handleJspIncludesErrors() mapped.
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1208)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:759)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:388)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:293)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4727)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5167)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
    at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1101)
    at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1786)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping com.sdl.webapp.common.controller.BaseController.requestMappingHandlerMapping; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'pageController' bean method 
public java.lang.String com.sdl.webapp.common.controller.BaseController.handleJspIncludesErrors()
to {[/system/mvc/Shared/Error/SectionError],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'campaignRedirectsController' bean method
public java.lang.String com.sdl.webapp.common.controller.BaseController.handleJspIncludesErrors() mapped.
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 26 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'pageController' bean method 
public java.lang.String com.sdl.webapp.common.controller.BaseController.handleJspIncludesErrors()
to {[/system/mvc/Shared/Error/SectionError],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'campaignRedirectsController' bean method
public java.lang.String com.sdl.webapp.common.controller.BaseController.handleJspIncludesErrors() mapped.
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1572)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1120)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1044)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
    ... 28 more
Caused by: java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'pageController' bean method 
public java.lang.String com.sdl.webapp.common.controller.BaseController.handleJspIncludesErrors()
to {[/system/mvc/Shared/Error/SectionError],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'campaignRedirectsController' bean method
public java.lang.String com.sdl.webapp.common.controller.BaseController.handleJspIncludesErrors() mapped.
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.registerHandlerMethod(AbstractHandlerMethodMapping.java:179)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.detectHandlerMethods(AbstractHandlerMethodMapping.java:145)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.initHandlerMethods(AbstractHandlerMethodMapping.java:107)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.afterPropertiesSet(AbstractHandlerMethodMapping.java:87)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1631)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1568)
    ... 38 more

EDIT:

Following @Alexey's suggestion we changed our controllers to NOT extend BaseController and now we are not getting the ambiguous mapping related in the logs. However now we are getting a different error regarding PageModel. Please see the error below. Kindly let us know what could be the cause of this error and how can we resolve the same.

java.lang.NullPointerException
at com.sdl.webapp.tridion.mapping.PageBuilderImpl.createPageModel(PageBuilderImpl.java:322)
at com.sdl.webapp.tridion.mapping.PageBuilderImpl.createPage(PageBuilderImpl.java:255)
at com.sdl.webapp.tridion.mapping.ModelBuilderPipeline.createPageModel(ModelBuilderPipeline.java:72)
at com.sdl.webapp.tridion.mapping.AbstractDefaultProvider$1.tryFindPage(AbstractDefaultProvider.java:287)
at com.sdl.webapp.tridion.mapping.AbstractDefaultProvider$1.tryFindPage(AbstractDefaultProvider.java:267)
at com.sdl.webapp.tridion.mapping.AbstractDefaultProvider.findPage(AbstractDefaultProvider.java:102)
at com.sdl.webapp.tridion.mapping.AbstractDefaultProvider.getPageModel(AbstractDefaultProvider.java:267)
at com.sdl.webapp.common.controller.PageController.getPageModel(PageController.java:321)
at com.sdl.webapp.common.controller.PageController.handleGetPage(PageController.java:129)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:100)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:604)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:565)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:617)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
at org.apache.coyote.ajp.AbstractAjpProcessor.process(AbstractAjpProcessor.java:844)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2463)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2452)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)

Edit: we have upadatd some of the jars files and now logging is working. Now in tridion.core log file, there is an error message "ClassPathBeanDefinitionScanner - Ignored because not matching any filter" for all the classes (dxa modules and custom classes)

2016-06-27 15:15:28,497 DEBUG ClassPathBeanDefinitionScanner - Identified candidate component class: file [D:\Apache\tomcat-sh-web13\webapps\ROOT\WEB-INF\classes\com\sdl\webapp\main\WebAppConfiguration.class]
2016-06-27 15:15:28,497 TRACE ClassPathBeanDefinitionScanner - Scanning file [D:\Apache\tomcat-sh-web13\webapps\ROOT\WEB-INF\classes\com\sdl\webapp\main\WebAppInitializer.class]
2016-06-27 15:15:28,512 DEBUG ClassPathBeanDefinitionScanner - Identified candidate component class: file [D:\Apache\tomcat-sh-web13\webapps\ROOT\WEB-INF\classes\com\sdl\webapp\main\WebAppInitializer.class]
2016-06-27 15:15:28,512 TRACE ClassPathBeanDefinitionScanner - Scanning URL [jar:file:/D:/Apache/tomcat-sh-web13/webapps/ROOT/WEB-INF/lib/dxa-common-api-1.4.1-SNAPSHOT.jar!/com/sdl/webapp/common/api/content/ConditionalEntityEvaluator.class]
2016-06-27 15:15:28,512 TRACE ClassPathBeanDefinitionScanner - Ignored because not matching any filter: URL [jar:file:/D:/Apache/tomcat-sh-web13/webapps/ROOT/WEB-INF/lib/dxa-common-api-1.4.1-SNAPSHOT.jar!/com/sdl/webapp/common/api/content/ConditionalEntityEvaluator.class]
2016-06-27 15:15:28,512 TRACE ClassPathBeanDefinitionScanner - Scanning URL [jar:file:/D:/Apache/tomcat-sh-web13/webapps/ROOT/WEB-INF/lib/dxa-common-api-1.4.1-SNAPSHOT.jar!/com/sdl/webapp/common/api/content/ContentProvider.class]
2016-06-27 15:15:28,512 TRACE ClassPathBeanDefinitionScanner - Ignored because not matching any filter: URL [jar:file:/D:/Apache/tomcat-sh-web13/webapps/ROOT/WEB-INF/lib/dxa-common-api-1.4.1-SNAPSHOT.jar!/com/sdl/webapp/common/api/content/ContentProvider.class]
2016-06-27 15:15:28,512 TRACE ClassPathBeanDefinitionScanner - Scanning URL [jar:file:/D:/Apache/tomcat-sh-web13/webapps/ROOT/WEB-INF/lib/dxa-common-api-1.4.1-SNAPSHOT.jar!/com/sdl/webapp/common/api/content/ContentProviderException.class]
2016-06-27 15:15:28,512 TRACE ClassPathBeanDefinitionScanner - Ignored because not matching any filter: URL [jar:file:/D:/Apache/tomcat-sh-web13/webapps/ROOT/WEB-INF/lib/dxa-common-api-1.4.1-SNAPSHOT.jar!/com/sdl/webapp/common/api/content/ContentProviderException.class]
2016-06-27 15:15:28,512 TRACE ClassPathBeanDefinitionScanner - Scanning URL [jar:file:/D:/Apache/tomcat-sh-web13/webapps/ROOT/WEB-INF/lib/dxa-common-api-1.4.1-SNAPSHOT.jar!/com/sdl/webapp/common/api/content/ExternalContentProvider.class]
2016-06-27 15:15:28,512 TRACE ClassPathBeanDefinitionScanner - Ignored because not matching any filter: URL [jar:file:/D:/Apache/tomcat-sh-web13/webapps/ROOT/WEB-INF/lib/dxa-common-api-1.4.1-SNAPSHOT.jar!/com/sdl/webapp/common/api/content/ExternalContentProvider.class]
2016-06-27 15:15:28,512 TRACE ClassPathBeanDefinitionScanner - Scanning URL [jar:file:/D:/Apache/tomcat-sh-web13/webapps/ROOT/WEB-INF/lib/dxa-common-api-1.4.1-SNAPSHOT.jar!/com/sdl/webapp/common/api/content/LinkResolver.class]
2016-06-27 15:15:28,512 TRACE ClassPathBeanDefinitionScanner - Ignored because not matching any filter: URL [jar:file:/D:/Apache/tomcat-sh-web13/webapps/ROOT/WEB-INF/lib/dxa-common-api-1.4.1-SNAPSHOT.jar!/com/sdl/webapp/common/api/content/LinkResolver.class]
2016-06-27 15:15:30,603 TRACE ClassPathBeanDefinitionScanner - Scanning file [D:\Apache\tomcat-sh-web13\webapps\ROOT\WEB-INF\classes\com\sdl\dxa\modules\generic\model\Brand.class]
2016-06-27 15:15:30,603 TRACE ClassPathBeanDefinitionScanner - Ignored because not matching any filter: file [D:\Apache\tomcat-sh-web13\webapps\ROOT\WEB-INF\classes\com\sdl\dxa\modules\generic\model\Brand.class]
2016-06-27 15:15:30,603 TRACE ClassPathBeanDefinitionScanner - Scanning file [D:\Apache\tomcat-sh-web13\webapps\ROOT\WEB-INF\classes\com\sdl\dxa\modules\generic\model\BrandAwards.class]
2016-06-27 15:15:30,603 TRACE ClassPathBeanDefinitionScanner - Ignored because not matching any filter: file [D:\Apache\tomcat-sh-web13\webapps\ROOT\WEB-INF\classes\com\sdl\dxa\modules\generic\model\BrandAwards.class]
2016-06-27 15:15:30,603 TRACE ClassPathBeanDefinitionScanner - Scanning file [D:\Apache\tomcat-sh-web13\webapps\ROOT\WEB-INF\classes\com\sdl\dxa\modules\generic\model\BrandList.class]
2016-06-27 15:15:30,603 TRACE ClassPathBeanDefinitionScanner - Ignored because not matching any filter: file [D:\Apache\tomcat-sh-web13\webapps\ROOT\WEB-INF\classes\com\sdl\dxa\modules\generic\model\BrandList.class]

Edit: This is our initializer code

@Component
@ComponentScan("com.sdl.dxa.modules.generic")
@RegisteredViewModels({
        @RegisteredViewModel(viewName = "CustomTeaser_jsp", modelClass = CustomTeaser.class, controllerName = "Generic"),
        @RegisteredViewModel(viewName = "CodeBlock_jsp",  modelClass = CodeBlock.class, controllerName = "Generic"),
        @RegisteredViewModel(viewName = "SiteMap_jsp", modelClass = SitemapItem.class, controllerName = "Generic"),
        @RegisteredViewModel(viewName = "ShortArticle_jsp", modelClass = Article.class, controllerName = "Generic"),

This is our controller code.

@Controller
public class CampaignRedirectsController {

    // TODO: Move this to common-impl or core-module

    private static final Logger LOG = LoggerFactory.getLogger(CampaignRedirectsController.class);

    private final UrlPathHelper urlPathHelper = new UrlPathHelper();
    private final ContentProvider contentProvider;
    private final LinkResolver linkResolver;
    private final MediaHelper mediaHelper;
    private final WebRequestContext webRequestContext;
    private final Markup markup;
    private final ViewResolver viewResolver;
    private final DataFormatter dataFormatters;
    @Value("#{environment.getProperty('AllowJsonResponse', 'false')}")
    private boolean allowJsonResponse;

    @Autowired
    public CampaignRedirectsController(ContentProvider contentProvider, LinkResolver linkResolver, MediaHelper mediaHelper,
                                       WebRequestContext webRequestContext, Markup markup, ViewResolver viewResolver, DataFormatter dataFormatter) {
        this.contentProvider = contentProvider;
        this.linkResolver = linkResolver;
        this.mediaHelper = mediaHelper;
        this.webRequestContext = webRequestContext;
        this.markup = markup;
        this.viewResolver = viewResolver;
        this.dataFormatters = dataFormatter;
    }

    private static boolean isIncludeRequest(HttpServletRequest request) {
        return request.getAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE) != null;
    }

    @RequestMapping(method = RequestMethod.GET, value = {"/{shortcutName}",
            "/f/{shortcutName}",
            "/g/{shortcutName}",
            "/l/{shortcutName}",
            "/t/{shortcutName}",
            "/i/{shortcutName}",
            "/s/{shortcutName}",
            "/q/{shortcutName}",
            "/e/{shortcutName}"}, produces = {MediaType.TEXT_HTML_VALUE, MediaType.ALL_VALUE})
    public String handleCampaignRedirectsPage(@PathVariable Map pathVariables, HttpServletRequest request, HttpServletResponse response) throws Exception {
10
  • Could you share (a part of) the controller code as well?
    – Quirijn
    Commented Jun 13, 2016 at 16:42
  • @Quirijn I have just edited the post to add some more info along with code fragment from the conflicting controller. Commented Jun 13, 2016 at 19:52
  • I think the issue is in the fact that DXA's BaseController is an abstract class with requestMappings. Since you cannot have the same mapping twice, you cannot extend the base class twice either. A work-around would be to override both methods which have request mappings, and provide a different mapping for them (if you need them at all). See github.com/sdl/dxa-web-application-java/blob/… for the source code of the BaseController.
    – Quirijn
    Commented Jun 13, 2016 at 20:10
  • @Quirijn We have another controller that has specific RequestMapping which should not conflict with the RequestMapping of DXA PageController. However this controller is causing conflict due to another method: @RequestMapping(method = RequestMethod.GET, value = {"/{shortcutName}", "/f/{shortcutName}", "/g/{shortcutName}", "/e/{shortcutName}"}, produces = {MediaType.TEXT_HTML_VALUE, MediaType.ALL_VALUE}) This causes a conflict with handleViewNotFoundErrors method of BaseController and I'm not sure how to override this with unique RequestMapping. Any suggestions? Commented Jun 14, 2016 at 10:16
  • After update, NPE: you have a NPE there because pageModelType is null. This is because Class pageModelType = viewModelRegistry.getViewModelType(pageMvcData) returned null at line 311. The most probable reason for this is that you have some view that is not registered with a model class. If you have your own views, you should register them properly with @RegisteredViewModel annotation (see core module).
    – Alexey
    Commented Jun 20, 2016 at 8:59

1 Answer 1

1

As @Quirijn has mentioned, BaseConroller is an abstract class that contains this mapping. When you extend it with an implementation, Spring maps base methods to concrete-class-@RequestMapping + method-@RequestMapping.

For PageController mapping if / since no explicit mapping is provided. Thus the resulting mapping for handleJspIncludesErrors() is / + /system/mvc/ + Shared/Error/SectionError = /system/mvc/Shared/Error/SectionError.

Your controller also has no explicit mapping, so uses the default one which is /. The resulting mapping for your controller's handleJspIncludesErrors() is also /system/mvc/Shared/Error/SectionError which is now ambiguous mapping.

This is actually a structural bug in DXA that BaseController doesn't allow to extend itself twice with the same base mapping, and shall be fixed in some future.

Currently you should either define a different from / @RequestMapping on a @Controller level, or not extend BaseController.

3
  • reported as github.com/sdl/dxa-web-application-java/issues/45 Commented Jun 15, 2016 at 14:51
  • @Alexey so you're saying we are forced to override all methods of BaseController in our Custom Controller even if we don't need to customize those methods? What unique mappings can I define for handleJspIncludesErrors() and handleViewNotFoundErrors() methods? Is it possible to write my own controller without extending from BaseController? I tried and that didn't work for me. Commented Jun 15, 2016 at 15:07
  • You're not forced to override BaseController methods. And defining custom mappings for these methods is not a good idea because you'll then have multiple mapping for actually the same functionality. You should only extend BaseController is you want to reuse something from it. You still can create your own controller without this base one. These are all normal Spring MVC controllers. Take a look at SiteMapXmlController that is a controller and is not a child of BaseController
    – Alexey
    Commented Jun 15, 2016 at 15:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.