Joker
Joker

Reputation: 11156

Unable to resolve Generic error in REST API

I am creating a rest web service where one app user can have multiple roles using generics.

I am stuck at a point and need help to move further. Kindly check the code below where I am getting compilation error.

My business logic is given below:

I am getting following error in service method as shown in code below:

Compilation fails here setRoles(Set< AppUserRoleEntity >) not applicable for the arguments (Set< AppUserRoleResource >)

Interface used

   public interface AppUserRole {
        void setRole(UserRole role);
    }
    public interface AppUser<T extends AppUserRole> {
        void setRoles(Set<T> appUserRoles);
    }

    public interface AppUserService <T extends AppUser<AppUserRole>>{
        T create(T username) throws Exception;
    }

Resources used

    // App user resource will get JSON data from REST
    public class AppUserResource implements AppUser<AppUserRoleResource> {
        //An app user can have mutilple roles
        Set<AppUserRoleResource> roles;
        public void setRoles(Set<AppUserRoleResource> appUserRoles) {
        this.roles = appUserRoles;
        }
    }
    public class AppUserRoleResource extends DefaultResource implements AppUserRole {
        private UserRole role;
        public UserRole getRole() {
            return role;
        }
        public void setRole(UserRole role) {
            this.role = role;
        }

    }

API used

    // Api will call service method to create user
    @RestController
    @RequestMapping(value = "/rest/users", produces = { APPLICATION_JSON_VALUE })
    public class AppUserApi {
    private AppUserService service;
    @RequestMapping(consumes = { APPLICATION_JSON_VALUE }, method = RequestMethod.POST)
    public void create(@RequestBody AppUserResource res) throws Exception {
            service.create(res);
    }
    }

Service used

    //Service will create entity object to save in data base
    public class AppUserServiceImpl implements AppUserService {
        public AppUser<AppUserRole> create(AppUserResource username) throws Exception {
            AppUserEntity obj = new AppUserEntity();
 // Compilation fails here setRoles(Set< AppUserRoleEntity >) not  
 // applicable for the arguments (Set< AppUserRoleResource >)
            obj.setRoles( username.getRoles());
            appUserRepository.save(obj);

        }

    }

Entity used

    public class AppUserEntity implements AppUser<AppUserRoleEntity> {
        private Set<AppUserRoleEntity> appUserRoles;
        public void setRoles(Set<AppUserRoleEntity> appUserRoles) {
            this.appUserRoles = appUserRoles;
        }
    }
    public class AppUserRoleEntity implements AppUserRole {
        private UserRole role;
        private AppUserEntity appUser;
        public void setRole(UserRole role) {
            this.role = role;

        }

Kindly check and share your inputs to fix this problem. I am completely stuck and not able to move further.

Upvotes: 0

Views: 395

Answers (1)

davidxxx
davidxxx

Reputation: 131356

AppUserRoleResource and AppUserRoleEntity are not assignable between them.
So you cannot assign a Set of one with a Set of the other.
These have the same base class, that's all :

public class AppUserRoleResource extends DefaultResource implements AppUserRole {...}

public class AppUserRoleEntity implements AppUserRole {...}

Besides, even if a AppUserRoleResource object could be assigned to a AppUserRoleEntity variable, you could not do the same thing with a collection of generic of these types without using a bounded wildcard with as upper bound the super type it its declaration : <? extends AppUserRoleEntity>

To solve your problem, you may write a mapper method that converts a Set<AppUserRoleResource> to a Set<AppUserRoleEntity>. You could so write :

AppUserEntity obj = new AppUserEntity();
obj.setRoles(mapper.mapToRoleEntities(username.getRoles()));

Or you can also use mapper libraries that map class fields by reflection (modelmapper, dozer) or generated code to do that (mapstruct)

Upvotes: 1

Related Questions