What does the value in @RestController annotation do?

Viewed 4691

Creating a simple Spring Boot application using Maven. I have given a value with RestController annotation, but it doesn't work. If I don't use the RestController's value, it works. I want to know, why it's not working and What's the use of value in @RestController?

http://localhost:9090/app/hello this gives error

http://localhost:9090/hello this works fine

@RestController("/app") What's the purpose of "/app" this value inside @RestController annotation?

P.S: I know, I can use @RequestMapping("/app") on ScraperResource class.

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}
@RestController("/app")
public class ScraperResource {
    @GetMapping("hello")
    public String testController() {
        return "Hello";
    }
}

application.properties

server.port=9090
3 Answers

That is because the "/app" inside your RestController has nothing to do with your URL mapping, but rather with a "logical component" name being used internally Spring.

You should do this instead, if you want to prefix all your controller methods with /app (or just leave it out).

@RestController
@RequestMapping("/app")
public class ScraperResource {

    @GetMapping("hello")
    public String testController() {
        return "Hello";
    }
}

Without @RestController Spring won't know that this class should handle HTTP calls, so it is a needed annotation.

As per the Java Doc associated with the @RestController annotation, this is the meaning of the value that you are passing to it:

/**
     * The value may indicate a suggestion for a logical component name,
     * to be turned into a Spring bean in case of an autodetected component.
     * @return the suggested component name, if any (or empty String otherwise)
     * @since 4.0.1
     */
    @AliasFor(annotation = Controller.class)
    String value() default "";

As such, it does not influence or affect what URL your endpoint is accessible with. If you want to add a top-level mapping you can use the @RequestMapping("/app") on the class-level as you mentioned.

The parameter in the @Controller annotation allows you to name the Controller. In cases where there are multiple beans of the same type, the bean name can be used along with the @Qualifier annotation to let Spring know which component to inject during autowiring.

From the documentation:

When a component is autodetected as part of the scanning process, its bean name is generated by the BeanNameGenerator strategy known to that scanner. By default, any Spring stereotype annotation (@Component, @Repository, @Service, and @Controller) that contains a name value thereby provides that name to the corresponding bean definition.

If such an annotation contains no name value or for any other detected component (such as those discovered by custom filters), the default bean name generator returns the uncapitalized non-qualified class name.

Read more about autowire disambiguation, and how to use the component name with @Qualifier here.

By default, Spring resolves @Autowired entries by type. If more than one bean of the same type is available in the container, the framework will throw a fatal exception.

To resolve this conflict, we need to tell Spring explicitly which bean we want to inject.

When there are multiple beans of the same type, it's a good idea to use @Qualifier to avoid ambiguity.

Please note that the value of the @Qualifier annotation matches with the name declared in the @Component annotation of our FooFormatter implementation.

Related