Hi everyone in my project I have 2 classes a Login Class and a Sports Class. And I want to pull a specific field from the database in the Sports Class based on the user login.
So for example if my login is 12345 the database should pull the respective sport name based on my login.
How do I connect the 2 classes in such a way so that the database can pull data based on my login in the previous class?
You can have a singleton class and store user details in that class when login happened and later you can access that from any other class.
public class UserDetails{
private static UserDetails instance = new UserDetails();
private UserDetails(){}
private String userId;
public static UserDetails getInctance(){
return instance;
}
public String getUserId(){
return userId;
}
public void setUserId(String userId){
this.userId = userId;
}
}
Then in Login class,
UserDetails.getInctance().setUserId("12345");
In Sports Class,
String userId = UserDetails.getInctance().getUserId();
Then user userId in query.
I am assuming time of calling you have the user information.Then simply you can get the userid and pass as method argument to sports detail method.Try to make classes loosely coupled.
Related
I am working on spring MVC application.
I have got the results from the service call as shown in the below code.
I want to add two string elements before I send back the results to the UI.
Below is the code in my spring controller class:
MyTestDTO myTestDTOObj = new MyTestDTO();
myTestDTOObj.setSid(22);
myTestDTOObj.setUserName("James");
myTestDTOObj.setWelcomeName("James Gold Customer XXX");
List<MyTestDTO> results = myServiceCall.getMyResultsData(myTestDTOObj);
//in the above results object i don't have the username and welcomeName which i want to return to the web page from spring controller.
MyTestDTO.java contains the below properties and its setters and getters:
public class MyTestDTO implements Serializable{
private int sid;
private String userName;
private String welcomeName;
...
//few ore properties
//setters and getters
}
Please advise how to add the username and welcomeName in the results object in the controller so that I can get that values on my web page.
You need another DTO:
public class AnotherDTO {
private List<MyTestDTO> results;
private String username;
private String welcomeName;
//getters and setters
}
Simply return this object.
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
I have a situation where I define security roles for an organization. The choices are a set of known enumerated default values, and the possibility of any number of custom role. The roles define the permissions the employees have in the organization. For example, a user can be;
public enum Role
{
Owner, Administrator, User, Guest;
}
However, the organization could also want its own custom roles (e.g. A PowerUser). I am looking for the best way to declare an object that has a known enumerated list of values (thats an enum) but with the possibility of provide any number of custom values (thats a class).
A naive approach would be the following (adding a custom enum value):
public enum Role
{
Owner, Administrator, User, Guest, Custom;
public BaseRole asRole()
{
//switch statement returning the BaseRole depending on the enum value.
}
}
public class BaseRole
{
Set<Permission> permissions;
}
The problem with this option is that the glue code will became very verbose if the enum value custom is selected. Since the custom value which holds all possible custom role would behave differently that the other values, every function that accepts a Role will need special glue to handle custom.
Ideally, something like this would probably be the best:
public enum Role
{
Owner, Administrator, User, Guest, Set<Custom>;
}
edit:
for reference, the user class would be
public class User
{
Set<Role> roles;
}
A possible solution would be to look back in pseudo-enum implementations in the pre enum Java versions. E.g.:
public class Role {
public static final Role OWNER = new Role("OWNER");
public static final Role ADMIN = new Role("ADMIN");
public static final Role USER = new Role("USER");
public static final Role GUEST = new Role("GUEST");
private String name;
// getter, setter, constructor, toString(), hashCode(), equals()
}
So whenever a Role is required, you can use the final fields:
Role r = Role.OWNER;
And still define custom ones:
Role r = new Role("Cook");
With some caution, it may even allow for == equality checking between a variable and the predefined values, but I would advise against it (use equals() always).
Maybe what you're looking for is an EnumSet?
http://docs.oracle.com/javase/7/docs/api/java/util/EnumSet.html
This is the solution I went with.
public interface Role
{
String getName();
}
public enum StandardRole implements Role
{
Owner, Administrator, User, Guest;
#Override
public String getName()
{
return this.name();
}
}
public class CustomRole implements Role
{
private String name;
public CustomRole(String name)
{
this.name = name;
}
#Override
public String getName()
{
return this.name;
}
}
public class User
{
Set<Role> roles;
}
I am coding in blueJ. My objectives are this:
1)Write a User class
A User:
has a username e.g 'fj3'
has a userType which can be: 'user', 'editor' or 'admin'
has a name e.g 'Francis'
has a constructor which takes the username, userType and name as parameters
has a getUsername() method
has a getUserType() method
has a getName() method
has a setUserType() method which takes one of the user types as a parameter
2)Write a UserGroup class
-The UserGroup class must have an ArrayList of Users.
Write a constructor for the UserGroup class. It should instantiate the ArrayList.
In UserGroup write a method called .addSampleData() which creates 10 Users and using the ArrayList's add() method put the 10 new User objects into the ArrayList.
In UserGroup write a getUser method which takes an int as a parameter and returns the User in that slot of the ArrayList.
In UserGroup write a printUsernames() method in UserGroup:
Using an enhanced for loop (see above), loop through the ArrayList and print the username and userType of each user in the ArrayList.
What I have so far is:
package user;
public class User{
public enum UserType{
ADMIN, EDITOR, USER;
}
private String id;
private UserType userPermissions;
private String actualName;
public User(String username, UserType userType, String name){
id = username;
userPermissions = userType;
actualName= name;
}
public String getUsername(){
return id;
}
public UserType getUserType(){
return userPermissions;
}
public String getName(){
return actualName;
}
public void setUserType(UserType input){
userPermissions = input;
}
}
And my UserGroup class:
package user;
import java.util.*;
import user.User.UserType;
public class UserGroup{
private ArrayList<User> people;
public UserGroup(){
people = new Arraylist<User>();
}
public static void addSampleData(String username, UserType userType, String name){
People.add(new User(username, userType,name));
}
public String getUser(int list){
return User;
}
public void printUsernames(){
for (User user: groupArray){
System.out.printf("%s %s\n", user.getUsername(), user.getuserType);
}
}
}
This is obviously far from being complete but I am completely stuck. My first problem is that "for (User user : groupArray)" is giving me the error illegal start of type. Please help me with this!! I think my User class is fine but my UserGroup class is nowhere enar completing all the objectives and I don't know how to do them!!
The specification requires a UserGroup's list of users to be
instantiated within the constructor. Thus, it should be not be
static but an instance variable:
public class UserGroup {
private ArrayList<User> people;
public UserGroup() {
people = new ArrayList<User>();
}
// ...
}
This way, you can create multiple UserGroup instances, each having their own list of users. With a static variable, this would not be possible.
Your getUser(int) method does not do what it is supposed to do and
will not compile. You are returning the type User there instead of
a specific User instance.
The enhanced for loop you use for printing user names is a free floating block of code. It should be inside the method printUsernames() as prescribed by your specification.
Your User class will work fine, but its instance variables should be private instead of public.
To resolve your import issues, put your User class into a package, e.g. user, and have UserGroup import User.UserType (the "User." part is needed since UserType is an inner class within User) from this package.
package user;
public class User{
// ...
}
package user;
import java.util.*;
import user.User.UserType;
public class UserGroup{
// ...
}
To iterate through the users in the arraylist, your enhanced for loop should be like this:
for (User user: groupArray)
System.out.printf("%s %s\n", user.getUsername(), user.getuserType);
EDIT:
To adhere more effectively to the question and to be more conventional, the ArrayList should be declared then instantiated after.
private static ArrayList<User> UserGroup;
public UserGroup() {
UserGroup = new ArrayList<>();
}
Your use of "Package" in your import seems suspicious:
import package.User.UserType;
as usually this would be
import User.UserType;
or actually more commonly:
import user.UserType;
since package names by convention should begin with a lower-case letter.
In the future, please be sure to include your package statements with your code if the package name is relevant to the question.
Lets say I have a table like this
USER_ID USERNAME PASSWORD DATE_CREATED DATE_LAST_LOGIN
1 'user1' 'password1' '12-Jun-2010' '12-Nov-2010'
2 'user2' 'password2' '14-Jun-2010' '12-Nov-2010'
Which is mapped to a POJO class using hibernate like this
#Entity
#Table( name="user" )
public class User {
private Integer id;
private String username;
private String password;
private Date dateCreated;
private Date dateLastLogin;
public User() {
}
#Id
#GeneratedValue( strategy = GenerationType.IDENTITY )
public IntegergetId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Colum( name="USERNAME" )
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
#Colum( name="PASSWORD" )
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password= password;
}
#Colum( name="DATE_CREATED" )
public Date getDateCreated() {
return dateCreated;
}
public void setDateCreated(Date dateCreated) {
this.dateCreated= dateCreated;
}
#Colum( name="DATE_LAST_LOGIN" )
public Date getDateLastLogin() {
return dateLastLogin;
}
public void setDateLastLogin(Date dateLastLogin) {
this.dateLastLogin = dateLastLogin;
}
}
This class will be used in two ways,
1. Authenticate a user for login and when the user logs in the DATE_LAST_LOGIN will be updated with the current date.
2. Update user details in a user edit form.
My problem is that I only ever want to update the DATE_LAST_LOGIN field when the user logs in, not when editing a user in the form. If I were to load a User record and then save it without calling setDateLastLogin then that would be fine until the time comes that a user logs in in-between the load and update operations. This will cause the DATE_LAST_LOGIN to be updated in the db but then when the user edit form saves the changes it will override the DATE_LAST_LOGIN with the old, incorrect value.
EDIT:
I don't think I explained the situation fully so here is some more info .... This is specifically in a webapp, the update of the user happens like so.
User record loaded and used to populate an html form
The form is edited and submitted back to the server
The server commits the changes to the database
As it stands I to not query the object from the database again before updating on form submission, i just populate a new object with the fields from the form and save it to the database, this of course means that the dateLastLogin is null at the time of saving the update and so would replace the correct value with null in the DB. This obviously could not be solved by simply synchronizing threads. Before hibernate I would simply have chosen not to update the DATE_LAST_LOGIN field but hibernate is not allowing me to make that design time decision.
An alternative would be to query the object before overwriting with the fields from the form, however this forces me to have to run a query before the update which I would not have to do without hibernate, and this would force me to use the synchronization that was suggested in one answer. The problem with that is that synchronization would only apply in the current application, if I had multiple apps updating the same DB then it would be useless.
Which comes back to my original question, is there a way to exclude the field from the update, if not by simply asking hibernate to do so then perhaps by a different system design.
My suggestion would be to use 2 different entities for the user, e.g. User and UserLogin (where the later would extend the regular User and hold the dateLastLogin property) and to use UserLogin during authentication and the short User when editing the user details.
This is a synchronization problem more than an Hibernate one. You should make your two operations (login and edition of user) atomic with respect to each other. That can be achieved by simple Java synchronization (common mutex or lock before entering these operations Java methods) or by database (i.e. Hibernate) transaction management.
Can you control this with a switch (boolean) value that you can toggle as needed and then add this check to the setter?
eg:
boolean dateLastLoginUpdatable = false;
public void setDateLastLogin(Date dateLastLogin) {
if( dateLastLoginUpdatable ) {
this.dateLastLogin = dateLastLogin;
}
}
public void toggleLastLoginEditable( boolean newValue ) {
dateLastLoginUpdatable = newValue;
}
Ok so I came up with my own solution which works for me though I don't know if there is not a better solution at present.
Basically in my POJO I have made the getDateLastLogin field read only by adding updatable = false to the annotation like so
#Colum( name="DATE_LAST_LOGIN", updatable = false )
public Date getDateLastLogin() {
return dateLastLogin;
}
Then when logging in I bypass the POJO and update the database directly with an HQL update in my login controller a little bit like this
public void login(String username, String password) {
User user = getUser( username, password );
if( user != null ) {
Query userUpdate = getSession().createQuery( "update User set dateLastLogin = current_timestamp where id = :userId" );
userUpdate.setInteger( "userId", user.getId() );
userUpdate.executeUpdate();
}
}