Search code examples
spring-bootmappingjavabeansspring-restcontroller

Problem with registering controller using @Bean annotation in class annotated with @Configuration


I have recently updated my project to spring boot v 3.0.6 (from 2.2.5) and Java version 17 (from 11). My approach is to register the controller not by using class-level annotations (like @Controller or @RestController) but instead by using the method shown below.

Configuration class:

@Configuration
class CampaignConfig {

    @Bean
    CampaignController campaignController(CampaignRepository campaignRepository,
        MongoOperations mongoOperations, MongoTemplate mongoTemplate,
        ExternalApiFacade externalApiFacade) {
        final var campaignMapper = new CampaignMapperImpl();
        final var campaignWriterService = campaignWriterService(
            campaignRepository, mongoTemplate, externalApiFacade,
            campaignMapper);
        final var campaignReaderService = new CampaignReaderServiceImpl(mongoOperations,
            campaignMapper);
        return new CampaignController(campaignWriterService, campaignReaderService);
    }
}

Controller class:

@AllArgsConstructor
@RequestMapping("/panel/campaign")
class CampaignController {

    private CampaignReaderService campaignReaderService;

    @GetMapping
    @ResponseBody
    public List<CampaignRestDto> getCampaign(
        @RequestParam(required = false) CampaignType campaignType,
        @RequestParam(required = false) Set<CampaignStatus> campaignStatus,
        @RequestParam(required = false) Long campaignId,
        @RequestParam(required = false) Long oddsProviderId) {

        final var searchCriteria = CampaignSearchCriteria.builder()
            .campaignType(campaignType)
            .campaignStatuses(campaignStatus)
            .campaignId(campaignId)
            .oddsProviderId(oddsProviderId)
            .build();

        return campaignReaderService.getCampaigns(searchCriteria);
        
    }
}

In spring boot 2 this approach works like charm. CampaignController is registered as a bean and starting my app locally on port 8080 I can access the endpoint http://localhost:8080/panel/campaign. In spring boot 3 this approach doesn't work. Bean is registered but the endpoint http://localhost:8080/panel/campaign is not accessible.

To test it further I added a logging logging.level.org.springframework.web=TRACE

and registered a dummy controller with class-level annotation

@RestController
public class TestController {

    @GetMapping("/test")
    public String getTest(){
        return "test";
    }
}

When I run the app I can see in the logs:

2023-04-26T11:28:31.102+02:00 TRACE 4552 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : 
    p.c.a.a.s.p.c.r.TestController:
    {GET [/test]}: getTest()

but no logs related to CampaignController.

Is this a bug in spring boot 3, or this way of creating controllers is no longer supported, or am I missing something?


Solution

  • Yes Springframework 6 (implicit in Springboot 3) requires controllers to be annotated with @Controller (so also @RestController) to be detected as a controller.