javagenericsraw-types

REST API: Raw Type warning extending a Generic Class


I have a bunch of RestController classes which look something like this:

public class CategoryController {

    private final IModelService modelservice;
    private final ICacheHelper cacheHelper;

    public CategoryController (IModelService modelservice, ICacheHelper cachehelper) {
    this.modelservice = modelservice;
    this.cachehelper = cachehelper;

    @GetMapping("/foo/bar")
    public ResponseEntity<Model1> getModel1 () {
        Model1 model1 = modelService.getModel1();

        if (model1 == null) {
            return ResponseEntity.notFound().build();
        }
    return ResponseEntity.ok().build();
    }

    @GetMapping("/foo/bar/baz")
    public ResponseEntity<Model2> getModel2 () {
        Model2 model2 = modelservice.getModel2();

        if (model2 =? null) {
            return ResponseEntity.notFound().build();
        }
    return ResponseEntity.ok().build();
    }
}

So I created a Base.class which contains the following

public class Base<T> {

    private final ICacheHelper cachehelper;

    public Base(ICacheHelper cachehelper) {
        this.cachehelper = cachehelper;

    public ResponseEntity<T> simpleResponse(T object, CacheControl cacheControl) {
        return object != null
            ? ResponseEntity.ok().cacheControl(cacheControl).body(object)
            : ResponseEntity.notFound().cacheControl(cacheHelper.getErrorMaxAge()).build();

I then extended the CategoryController with Base but without generics. So I could use my simpleResponse. Rightfully I get lots of warnings of unchecked assignments in IntelliJ. The more i read about generics the more i understand that this is simply not a good idea and only possible because of legacy reasons.

Has anyone an idea how to do this better and use generics the proper way? I thought of restructuring the RestController, and make them based on the returnValue. Which means that I need to create for every Model that I want to return a extra ControllerClass. Then I can i.e.

public class Model1Controller extends Base<Model1> {
    // do stuff
}

Is this a good API design or do you guys have other ideas to solve this problem. Another idea was instead of extending a Base.class I could do some kind of util class with static Methods. But I need to check this out first


Solution

  • You simply remove < T> from Base class and move < T> into the generic method. It will remove the warnings of unchecked castings:

    public class Base {
    
        private final ICacheHelper cachehelper;
    
        public Base(ICacheHelper cachehelper) {
            this.cachehelper = cachehelper;
        }
    
        public <T> ResponseEntity<T> simpleResponse(T object, CacheControl cacheControl) {
             // ...
        }
    
        public <A> ResponseEntity<A> anotherSimpleResponse(A object, CacheControl cacheControl) {
            // ...
        }
    }