0

I have 2 domain classes: User and Role. 1 User can have 1 or more Roles.

public class User implements Serializable {
   private String username;
   private String password;
   private boolean lockFlag;
   private List<Role> rolesList;
   // getters and setters 
}

public class Role implements Serializable {
   private int roleId;
   private String description;
   // getters and setters
}

In my service layer I have a method to login a user into the system. This method receives 3 arguments: String username, String password, int roleId and it throws an exception UserServiceException if an error occurs.

public void login(String username, String password, int roleId) throws UserServiceException;

The service method retrieve the User domain class along with associated Roles:

User user = userDAO.getUserById(username);

The service method retrieve the Role domain class:

Role role = roleDAO.getRoleById(roleId);

The service method perform no. of checks. Assuming all checks are passed, service method needs to tell its caller that the login was successful and send the user object and the role object. That's where I am confused how to send them. I have come up with some options:


OPTION 1:

Change the service method signature to return object of User domain class:

public User login(String username, String password, int roleId) throws UserServiceException;

Change the User domain class to add one more property currentRole which is of Role class type:

public class User implements Serializable {
   private String username;
   private String password;
   private boolean lockFlag;
   private List<Role> rolesList;
   private Role currentRole;
   // getters and setters 
}

In my service method set the currentRole property of user object to the role object before sending the user object:

user.setCurrentRole(role);
return user;

OPTION 2:

Instead of changing the User domain class, create a DTO which resembles the User domain class + one more property currentRole which is of Role class type:

public class UserModelDTO implements Serializable {
   private String username;
   private String password;
   private boolean lockFlag;
   private List<Role> rolesList;
   private Role currentRole;
   // getters and setters 
}

Change the service method signature to return object of UserModelDTO class:

public UserModelDTO login(String username, String password, int roleId) throws UserServiceException;

In my service method create an object of UserModelDTO class and send it:

UserModelDTO userModelDTO = new UserModelDTO();
userModelDTO.setUsername(user.getUsername());
userModelDTO.setPassword(user.getPassword());
userModelDTO.setLockFlag(user.getLockFlag());
userModelDTO.setRolesList(user.getRolesList());
userModelDTO.setCurrentRole(role);
return userModelDTO;

OPTION 3:

Create a DTO which has 1 property user of User class type and 1 property role of Role class type:

public class UserRoleModelDTO implements Serializable {
   private User user;
   private Role role;
   // getters and setters 
}

Change the service method signature to return object of UserRoleModelDTO class:

public UserRoleModelDTO login(String username, String password, int roleId) throws UserServiceException;

In my service method create an object of UserRoleModelDTO class and send it:

UserRoleModelDTO userRoleModelDTO = new UserRoleModelDTO();
userRoleModelDTO.setUser(user);
userRoleModelDTO.setRole(role);
return userRoleModelDTO;

OPTION 4:

Change the service method signature to return a Map:

public Map login(String username, String password, int roleId) throws UserServiceException;

In my service method create a Map and send it:

Map map = new HashMap();
map.put("USER_DOMAIN", user);
map.put("ROLE_DOMAIN", role);
return map;

OPTION 5:

No link to domain classes.

Create a RoleModelDTO which resembles the Role class type.
Create a UserModelDTO which resembles the User class type.
In UserModelDTO, the property rolesList will refer to List of RoleModelDTO type.
In UserModelDTO, add one more property currentRole which is of RoleModelDTO class type:

public class RoleModelDTO implements Serializable {
   private int roleId;
   private String description;
   // getters and setters 
}

public class UserModelDTO implements Serializable {
   private String username;
   private String password;
   private boolean lockFlag;
   private List<RoleModelDTO> rolesList;
   private RoleModelDTO currentRole;
   // getters and setters 
}

Change the service method signature to return object of UserModelDTO class:

public UserModelDTO login(String username, String password, int roleId) throws UserServiceException;

In my service method create an object of UserModelDTO class and send it:

RoleModelDTO roleModelDTO = new RoleModelDTO();
roleModelDTO.setRoleId(role.getRoleId());
roleModelDTO.setDescription(role.getDescription());

List<RoleModelDTO> roleModelDTOList = new ArrayList<RoleModelDTO>();
for (Role role1 : user.getRolesList()) {
    RoleModelDTO roleModelDTO1 = new RoleModelDTO();
    roleModelDTO1.setRoleId(role1.getRoleId());
    roleModelDTO1.setDescription(role1.getDescription());
    roleModelDTOList.add(roleModelDTO1);
}

UserModelDTO userModelDTO = new UserModelDTO();
userModelDTO.setUsername(user.getUsername());
userModelDTO.setPassword(user.getPassword());
userModelDTO.setLockFlag(user.getLockFlag());
userModelDTO.setRolesList(roleModelDTOList);
userModelDTO.setCurrentRole(roleModelDTO);
return userModelDTO;



Which of the option should I go with? Is there any other option which makes the most sense? If yes please do share.

Some questions:

Does 1 service method should always return 1 domain class? In case of wanting to return more than 1 domain class, should we build a relationship between them?

Regarding Option 1, does it make sense to change a domain class to include something your caller (controller) need?

Regarding Options 2, 3 &4, does it make sense to return anything other than a domain class from the service method?

Which options might be breaking a design pattern?

UPDATE 1

I thought about another option which I have added as 5th option. This option sends a DTO but that DTO has no link to Domain model classes. Interesting concept.

Please reply about my question. I am in kind of a limbo and need some experienced developers guidelines to move me forward.

Thanks

srh
  • 1,661
  • 4
  • 30
  • 57
  • Why do you expect the role to be returned? Assumption would be that the user has the corresponding role assigned, wouldn't it? – GandalfIX Apr 08 '15 at 22:16
  • On the Controller side I need to store the specific Role which was used by the User to login in session. – srh Apr 08 '15 at 22:31
  • In that case I would go for a class like "public class AuthenticatedUser { User user; Role authenticatedRole}" which returns the corresponding fields as a composite. – GandalfIX Apr 14 '15 at 18:34
  • Would you refer to `AuthenticatedUser` as a DTO or a domain class? – srh Apr 14 '15 at 18:47
  • If you need it only to get the information to your frontend/controller I would call it DTO – GandalfIX Apr 15 '15 at 21:45
  • yes that's the only purpose. Basically it would be stored in session and I would pass it as a the 1st parameter of all methods in the service classes. Would you advise storing it in a different package than where the domain classes are stored? Or should it use the same package? For e.g. if domain classes are in `com.myapp.model.domain` package then should this `AuthenticatedUser` be store in the same package? or should it be in a package in service layer like `com.myapp.model.service.dto`? – srh Apr 16 '15 at 21:55

0 Answers0