rstoyanchev/spring-mvc-31-demo

Provide XML variant of introducing ExtendedRequestMappingHandlerMapping

smarek opened this issue · 7 comments

Can you please provide an example, of how can we introduce new @RequestMapping through XML

Regardless if there is need of using RequestMappingHandlerMapping subclass wrapper.

Thanks

The XML namespace is more limited than the MVC Java config when it comes to plugging in sub-classes of the infrastructure classes. What you can do is configure the extended handler mapping with the order property set to -1 so that it's one lower than the one created by the namespace.

I've literally used this:
The only HandlerMapping specified in whole project

<bean class="com.mycompany.myproject.mvc.mapping.CustomRequestMappingHandlerMapping">
        <property name="order" value="-2" />
        <property name="interceptors">
            <list>
                <ref bean="layoutInterceptor" />
                <ref bean="localeChangeInterceptor" />
                <ref bean="subdomainMappingInterceptor" />
                <ref bean="maintenanceInterceptor" />
            </list>
        </property>
    </bean>

    <bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
        <property name="order" value="-1" />
        <property name="flowRegistry" ref="flowRegistry" />
        <property name="interceptors">
            <list>
                <ref bean="layoutInterceptor" />
                <ref bean="localeChangeInterceptor" />
                <ref bean="subdomainMappingInterceptor" />
                <ref bean="maintenanceInterceptor" />
            </list>
        </property>
    </bean>

But on mappings creation, I got this difference:

Controller:

@RequestMapping("/rolemapping")
@SubdomainMapping("www")
function rolemapping( ... ){ ... }

My code:
Mapped "{[/rolemapping],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}"
This example project:
Mapped "{[/rolemapping],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[org.springframework.samples.mvc31.requestcondition.mvc.RolesRequestCondition@9c6a99d]}"

Condition is not injected at all through XML config I posted

It's your CustomRequestMappingHandlerMapping that contributes the mappings, so put a breakpoint and see what it returns.

It returns the underlying SubdomainRequestCondition correctly on not-null input.

getCustomMethodCondition: public java.lang.String com.mycompany.myproject.controllers.UsersController.login_users(java.util.Map)
createCondition: @com.mycompany.myproject.mvc.mapping.SubdomainMapping(value=[users])
src: com.mycompany.myproject.mvc.mapping.SubdomainRequestCondition@4de3e1b8
    private RequestCondition<?> createCondition(SubdomainMapping accessMapping) {
        System.out.println("createCondition: " + accessMapping);
        SubdomainRequestCondition src = null;
        src = (accessMapping != null) ? new SubdomainRequestCondition(
                accessMapping.value()) : null;
        System.out.println("src: " + src);
        return src;
    }

But right after that, on processing, my class CustomRequestMappingHandlerMapping is not called for mapping the addresses, but instead is called org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping, which returns

Caused by: java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'usersController' bean method ... there is already 'usersController' bean method mapped

So does that mean, that XML config I provided, is not sufficient, to map URLs by my extended HandlerMapping ?

Ok this sounds like a different problem. The CustomRequestMappingHandlerMapping is probably initializing correctly. Most likely the RequestMappingHandlerMapping registered by the mvc namespace rejects you controller because it finds two methods mapped in exactly the same way.

The mvc namespace is simply not designed for what you're trying to do. I thought it might work but it doesn't seem so . Your options are to drop it and replace it with explicit bean definitions (RequestMappingHandlerMapping, RequestMappingHandlerAdapter, and ExceptionHandlerExceptionResolver if using @ExceptionHandler methods) or to use the MVC Java config as this example does. Note that you can mix and match Java and XML configuration -- just create a WebConfig class similar to this example and declare it as a definition in your XML to have it included.

I've debugged this.

The problem comes from <mvc:annotation-driven /> XML config tag.

This element does some black magic, and is registering some default RequestMappingHandlerMapping, RequestMappingHandlerAdapter and common classes around as seen in implementation here

http://www.jarvana.com/jarvana/view/org/springframework/spring-webmvc/3.0.4.RELEASE/spring-webmvc-3.0.4.RELEASE-sources.jar!/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java?format=ok

But in XML namespace, there is no option to override the behavior. So I switched to Java Annotation ridden config, and everything suddenly started working as expected.

I'll rise an Spring JIRA issue, and close this bug after linking-through the bug with this issue.

Thanks for assistance @rstoyanchev

So the promised link:

https://jira.springsource.org/browse/SPR-9344

This ticket resolution, will give us the option, to override default beans implementations (if resolved as requested), and so properly map RequestMappingHandlerMapping subclasses and resolve many other issues, caused by this automagic config element.