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