Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Controller: Custom annotation with combined Spring annotations does not work

I have properly working Spring Controller, where I have a method mapped in a following way

@RequestMapping(
    value = "/users"
    consumes = MimeTypeUtils.APPLICATION_JSON_VALUE,
    produces = MimeTypeUtils.APPLICATION_JSON_VALUE,
    method = RequestMethod.GET)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public UserResponse retrieveUsers() {
    return new UserResponse();
}

@RequestMapping(
    value = "/contracts"
    consumes = MimeTypeUtils.APPLICATION_JSON_VALUE,
    produces = MimeTypeUtils.APPLICATION_JSON_VALUE,
    method = RequestMethod.GET)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public ContractResponse retrieveContracts() {
    return new ContractResponse();
}

This works fine, GET requests are served as accepted, and in case of for example POST I am receiving proper 405 status code.

Now I want to introduce custom combined annotation, not to have the same bunch of annotations in each and every method.

My custom annotation looks like,

@RequestMapping(
        consumes = MimeTypeUtils.APPLICATION_JSON_VALUE,
        produces = MimeTypeUtils.APPLICATION_JSON_VALUE,
        method = RequestMethod.GET)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Get {}

Accordingly, I change the method to

@Get
@RequestMapping(value = "/users")
public UserResponse retrieveUsers() {
    return new UserResponse();
}

In this case I can see that whatever type of request I send to /users it is served properly. For example even if I do POST, I see response. So the @RequestMapping does not work properly.

What am I doing wrong here? Is it possible to make controllers behave properly with custom combined annotation?

like image 857
vtor Avatar asked Jun 03 '26 18:06

vtor


2 Answers

I suspect that the @RequestMapping(value = "/users") on UserResponse#retrieveUsers replaces the @RequestMapping on the @Get interface.

See if this works:

@RequestMapping(
        consumes = MimeTypeUtils.APPLICATION_JSON_VALUE,
        produces = MimeTypeUtils.APPLICATION_JSON_VALUE,
        method = RequestMethod.GET)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Get {

    @AliasFor(annotation = RequestMapping.class, attribute = "value")
    String[] value() default {};
}

@Get(value = "/users")
public UserResponse retrieveUsers() {
    return new UserResponse();
}

You may be interested in GetJson in the spring-composed project.

Note that @AliasFor was only released with Spring 4.2. It's not available in earlier versions.

like image 51
whistling_marmot Avatar answered Jun 06 '26 07:06

whistling_marmot


You overwrite the @RequestMapping annotation you had set up in your @Get annotation. Therefore it specifies only the value part of the request mapping, leaving all other properties to default.

like image 27
0x0me Avatar answered Jun 06 '26 07:06

0x0me