CharlieShi
CharlieShi

Reputation: 916

Rest Service input param changed in spring boot

I am now extracting my project to three parts: a core project used for US & India with features that can by applied for both of them, a US project with US features only, a India project with India features only.

But now I get a problem that in spring boot. In US, there are two new fileds added to the original core entity, so the input object changed from PromSeckillRequest to UsPromSeckillRequest,

Now I want to override my seckill interface, I have no good choice but first write an abandon seckill interface and then write another seckill interface that I want. code below:

@RestController("usShoppingController")
@RequestMapping(value = "/prom", method = RequestMethod.POST)
public class UsPromShoppingController extends PromShoppingController {

@RequestMapping("/seckillAbandon")
@Override
public JsonResponse seckill(@Valid @RequestBody PromSeckillRequest request)    {
    return null;
}

@RequestMapping("/seckill")
public JsonResponse usSeckill(@Valid @RequestBody UsPromSeckillRequest request) {
        return super.seckill(request);
    }
}

But what my goal is like below:

@RestController("usPromShoppingController")
@RequestMapping(value = "/prom", method = RequestMethod.POST)
public class UsPromShoppingController extends PromotionShoppingController {

@RequestMapping("/seckill")
@Override
public JsonResponse usSeckill(@Valid @RequestBody UsPromSeckillRequest request) {
        return super.seckill(request);
    }
}

Is there any good resolution for this? I am using spring boot.

EDIT:

I checked with google and found that, it's a weak point for spring boot until now. I don't know why spring boot don't pay full supportage for this point. I think maybe we can do it like this only.

I want to add a wrapper to solve this, but seems I can only change the request to HashMap type Or String type, But this is not what I want Because it will hard to valid the input request params.

Upvotes: 0

Views: 617

Answers (1)

Christoph Grimmer
Christoph Grimmer

Reputation: 4313

Ok, from what information I have I will try to guess what exactly your problem is and how to fix it :-)

First of all I'm assuming that you somehow (e.g. using a profile) toggle which controller is active since you cannot have two controllers bound to the same endpoint. This is not really spring's fault but has to do with the routing inside the application server (e.g. tomcat).

Soooo... If you are using profiles you can use the active profile as a qualifier by simply annotating your controller class with @Profile and toggle which one is used. That way no overriding whatsoever is needed.

On top of that I strongly recommend that you remove the inheritance in lieu of composition. Put all your shared logic into a central class (like the one you inherit from) and inject it into your constructor.

Your code then might look something like this (I added some Lombok sugar on top)

@RestController
@PostMapping("/prom")
@Profile("us")
@RequiredArgsConstructor
public class UsShoppingController {

    private final ShoppingController helper;

    @RequestMapping("/seckill")
    public JsonResponse seckill(@Valid @RequestBody UsPromSeckillRequest request) {
        return helper.seckill(request);
    }
}

If you are using some older version of spring boot you have to add an onMethod Annotation to @RequiredArgsConstructor or write it by hand.

If you really need your two controllers to run in parallel at the same time you will have to add an indirection layer inside your application code which does the routing based on the parameter type. The application server cannot help you there.

Upvotes: 3

Related Questions