简体   繁体   中英

Spring Boot - Ambiguous Mapping

Pulling my hair out over this one, makes absolutely no sense

@RestController("/firmwareAShkcwdsdskl")
public class FirmwareController {
    @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Result> createNewFirmwareVersion(DetailedFirmwareVersionRequest detailedFirmwareVersionRequest) { 
    // Code Block
    }
}

@RestController("/jobs/firmwareUpgrade")
public class FirmwareUpgradeController {
    @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Result> createNewJob(DetailedFirmwareUpgradeRequest detailedFirmwareUpgradeRequest) {
    // Code Block
    }
}

Attempting to start my Spring Boot application with these two controllers is throwing the following error

Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map '/jobs/firmwareUpgrade' method 
eshepherd.admin.api.controller.FirmwareUpgradeController#createNewJob(DetailedFirmwareUpgradeRequest)
to {POST , produces [application/json]}: There is already '/firmwareAShkcwdsdskl' bean method
eshepherd.admin.api.controller.FirmwareController#createNewFirmwareVersion(DetailedFirmwareVersionRequest) mapped.

The class name, method name, request mapping and parameters are all unique, I just don't understand it.

As you can tell I've descended into pure frustration trying all kinds of string changes to just get it to work initially, but if anyone could help me identify the problem I'd be extremely grateful.

Edit: Using Spring-Boot 2.2.4

As you mentioned in your own answer: Yes, you misunderstood. This is an easy one to confuse.

@RestController 's value is the component name, not the request mapping path. Take a look at the source for org.springframework.web.bind.annotation.RestController#value .

It is very similar to org.springframework.stereotype.Component#value and the others in org.springframework.stereotype (in spring-context ). You have have the correct annotations now:

@RestController
@RequestMapping("/firmware")
public class FirmwareRestController {
    // ...
}

Okay.. I managed to get it compiling.. I think I was misunderstanding how you can use the @RestController annotation

If you provide

@RestController
@RequestMapping("/firmware")

Instead of

@RestController("/firmware")

It will build. I guess I had assumed the default argument on the controller would be more useful, and looked to be working as I expected from the build messages.

Hope this helps someone!

The framework is complaining that there exists a post path / from the 2 controllers where the mapping is not specified for any one of them hence it cannot distinguish the exact path.

Can you please try the following code:

@RestController
@RequestMapping("/firmwareAShkcwdsdskl")
public class FirmwareController {
    @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Result> createNewFirmwareVersion(DetailedFirmwareVersionRequest detailedFirmwareVersionRequest) { 
    // Code Block
    }
}


@RestController
@RequestMapping("/jobs/firmwareUpgrade")
public class FirmwareUpgradeController {
    @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Result> createNewJob(DetailedFirmwareUpgradeRequest detailedFirmwareUpgradeRequest) {
    // Code Block
    }
}

@RequestMapping at controller level should define the root path for all the APIs in that path say for example I have to create a controller related to feeds API I would do:

@RestController
@RequestMapping("/api/feeds")
class FeedsController {
    //Constructor inject fields here
    @Autowired
    FeedsController() {

    }

    @GetMapping("/")
    ResponseEntity<Map<String, String>> get() {
        return ResponseEntity.ok(Collections.emptyMap());
    }

    @PostMapping("/")
    ResponseEntity<Map<String, String>> post() {
        return ResponseEntity.ok(Collections.emptyMap());
    }

    /**
     * Standard way to implement delete is to soft delete
     * @return
     */
    @DeleteMapping("/")
    ResponseEntity<Map<String, String>> delete() {
        return ResponseEntity.ok(Collections.emptyMap());
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM