Affects: \

Due to business needs, we need to support dynamic registration or offline RequestMappingInfo, so we implement CustomRequestMappingHandlerMapping based on RequestMappingHandlerMapping like this.

@Component
public class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping {    
private Map<String, MappingInfoCacheVO> cache = new HashMap<>();
    @Override
    protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
        if(handler instanceof String){
            String beanName = (String) handler;
            String name = method.getName();
            cache.put(String.join("#", beanName, name), new MappingInfoCacheVO(handler, method, mapping));
        }
    }

    public MappingInfoCacheVO getCacheMappingInfo(String key){
        return cache.get(key);
    }

    static class MappingInfoCacheVO {
        Object handler;
        Method method;
        RequestMappingInfo mapping;

        public MappingInfoCacheVO(Object handler, Method method, RequestMappingInfo mapping) {
            this.handler = handler;
            this.method = method;
            this.mapping = mapping;
        }
    }
}

Then, we'll inject this cacheMapping into the controller so that we can use it in the request.

@Autowired
private CustomRequestMappingHandlerMapping mappingValue;

@PostMapping("/register")
public MappingInfoCacheVO register(@RequestParam String key){
    MappingInfoCacheVO reqVO = mappingValue.getCacheMappingInfo(key);
    mappingValue.registerMapping(reqVO.getMapping(), reqVO.getHandler(), reqVO.getMethod());
    return reqVO;
}

However, when I successfully registered, I got an Ambiguous exception when I made an HTTP request. Then I trying debug and found this define in the AbstractHandlerMethodMapping class. org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#register

public void register(T mapping, Object handler, Method method) {
    // Omit some of the content
    try {
        HandlerMethod handlerMethod = createHandlerMethod(handler, method);
        validateMethodMapping(handlerMethod, mapping);

        Set<String> directPaths = AbstractHandlerMethodMapping.this.getDirectPaths(mapping);
        for (String path : directPaths) {
            this.pathLookup.add(path, mapping);
        }
      // Omit some of the content
        this.registry.put(mapping,
                new AbstractHandlerMethodMapping.MappingRegistration<>(mapping, handlerMethod, directPaths, name, corsConfig != null));
    }
   // Omit some of the content
}

The method validateMethodMapping called here does not check whether the same mapping is registered. As a result, the same mapping information is registered in org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#pathLookup. Then an ambiguous exception occurs in the HTTP request .

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
    // Omit some of the content
    if (!matches.isEmpty()) {
        AbstractHandlerMethodMapping.Match bestMatch = matches.get(0);
        if (matches.size() > 1) {
            if (CorsUtils.isPreFlightRequest(request)) {
                // Omit some of the content
            }
            else {
                AbstractHandlerMethodMapping.Match secondBestMatch = matches.get(1);
                if (comparator.compare(bestMatch, secondBestMatch) == 0) {
                    Method m1 = bestMatch.getHandlerMethod().getMethod();
                    Method m2 = secondBestMatch.getHandlerMethod().getMethod();
                    String uri = request.getRequestURI();
                    throw new IllegalStateException(
                            "Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
                }
            }
        }
        return bestMatch.getHandlerMethod();
    }
}

So I wonder if this check should include the same mapping. org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#validateMethodMapping

Comment From: rstoyanchev

It's not clear what the goal is. Why does a mapping need to be registered twice?

Comment From: spring-projects-issues

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

Comment From: spring-projects-issues

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.