0

This is my controller

package example.infra.adapters.input.api.v1.endpoints

import example.aplication.services.authentication.LoginAuthenticator
import example.aplication.dtos.authentication.CredencialsDTO
import example.aplication.dtos.authentication.AuthenticationTokenDTO
import example.aplication.exceptions.authentication.AuthenticationErrorException

import org.springframework.web.bind.annotation.*
import org.springframework.http.ResponseEntity

import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import io.swagger.v3.oas.annotations.media.Content
import io.swagger.v3.oas.annotations.media.ExampleObject
import io.swagger.v3.oas.annotations.media.Schema
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.parameters.RequestBody

@RestController
@RequestMapping("/api/v1/authentication")
@Tag(name = "Authentication", description = "User authentication")
class AuthenticationApiController {

    LoginAuthenticator loginAuthenticator

    @PostMapping(value = "/token")
    @Operation(
        summary = "Get authentication token",
        requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
            required = true,
            content = @Content(
                mediaType = "application/json",
                schema = @Schema(implementation = CredencialsDTO),
                examples = [
                    @ExampleObject(
                        value = '{"login": "loginExample", "senha": "senhaExample"}'
                    )
                ]
            )
        ),
        responses = [
            @ApiResponse(
                responseCode = "200",
                description = "Success",
                content = @Content(
                    mediaType = "application/json",
                    schema = @Schema(implementation = AuthenticationTokenDTO),
                    examples = [
                        @ExampleObject(
                            value = '{"token": "abc123", "expiration": "2025-09-03T18:00:00Z"}'
                        )
                    ]
                )
            ),
            @ApiResponse(
                responseCode = "401",
                description = "Incorrect login or password",
                content = @Content()
            )
        ]
    )
    ResponseEntity<?> token(@org.springframework.web.bind.annotation.RequestBody CredencialsDTO credencials) {
        try {
            AuthenticationTokenDTO tokenDto = loginAuthenticator.authenticate(credencials)
            return JsonResponse.success(tokenDto)
        } catch (AuthenticationErrorException e) {
            return JsonResponse.unauthorized()
        }
    }
   
}

This is a simple "getToken" endpoint. But when I try to run my app (grails run-app --port 8080) I have this error:

| Running application... Configuring Spring Security Core ... ... finished configuring Spring Security Core 2025-09-04 14:58:23.510 ERROR --- [ restartedMain] o.s.boot.SpringApplication : Application run failedorg.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'authenticationApiController' method example.infra.adapters.input.api.v1.endpoints.AuthenticationApiController#token(CredencialsDTO) to {POST [/api/v1/authentication/token]}: There is already 'authenticationApiController' bean method example.infra.adapters.input.api.v1.endpoints.AuthenticationApiController#token() mapped. at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) at grails.boot.GrailsApp.run(GrailsApp.groovy:99) at grails.boot.GrailsApp.run(GrailsApp.groovy:485) at grails.boot.GrailsApp.run(GrailsApp.groovy:472) at grails.boot.GrailsApp$run.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:148) at agriwin.Application.main(Application.groovy:15) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'authenticationApiController' method example.infra.adapters.input.api.v1.endpoints.AuthenticationApiController#token(CredencialsDTO) to {POST [/api/v1/authentication/token]}: There is already 'authenticationApiController' bean method example.infra.adapters.input.api.v1.endpoints.AuthenticationApiController#token() mapped. at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.validateMethodMapping(AbstractHandlerMethodMapping.java:669) at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.register(AbstractHandlerMethodMapping.java:635) at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.registerHandlerMethod(AbstractHandlerMethodMapping.java:332) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.registerHandlerMethod(RequestMappingHandlerMapping.java:420) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.registerHandlerMethod(RequestMappingHandlerMapping.java:76) at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lambda$detectHandlerMethods$2(AbstractHandlerMethodMapping.java:299) at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.detectHandlerMethods(AbstractHandlerMethodMapping.java:297) at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.processCandidateBean(AbstractHandlerMethodMapping.java:266) at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.initHandlerMethods(AbstractHandlerMethodMapping.java:225) at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.afterPropertiesSet(AbstractHandlerMethodMapping.java:213) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.afterPropertiesSet(RequestMappingHandlerMapping.java:205) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ... 26 common frames omitted

Some considerations:

  • I don't have another "token" method in any controller of my project.
  • Im using java 8 + springboot 2.7.8 + grails 5.3
  • My dependencies about spring doc api: 'org.springdoc:springdoc-openapi-ui:1.8.0' and 'org.springdoc:springdoc-openapi-groovy:1.8.0'.
  • If I remove "Controller" from my file name and remove from my class declaration, like: AuthenticationApi.groovy -> Class AuthenticationApi {} it works, my project runs normally and my swagger works fine.
  • I've tryied to change my method name and no work, had the same problem.
  • I see some java examples, and they have a ExampleController.java with anotation @RestController, just it.
  • I had see some guys with this problem but they really have 2 methods mapped in a same endPoint and the solution is use @PostMapping(value = "...") to the different endPoints.
  • I can't find any groovy/grails project example with spring doc api swagger.

Any sugestions?

4
  • How does autenticacao relate to this problem? Is there another controller doing the same? Is there some residue from testing still around in the build directory (e.g. does cleaning the project help)? Commented Sep 5 at 6:12
  • @cfrick 'autenticacao' in this case means 'authenticate', i've just forgot to translate, sorry (i'll edit the question now). grails clean and ./gradlew clean build unfortunally dosn't help too. Commented Sep 5 at 13:47
  • I hope you did not mean literally translate. Manually changed error messages will miss-lead readers of the question. So please make sure, that the code and the error correlate. Is the controller-code complete? No second token method without an argument? The given token method not having a default argument for the CredentialsDTO? Commented Sep 6 at 7:46
  • @cfrick yes, the controller-code is complete. No second token method without argument. And token method don't have a default argument for the CredentialsDTO. This can't be a problem in my mind Commented Sep 8 at 20:13

0

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.