Use the session object UserBean across dao methods - java

I get an Object say UserBean something like this from the session
public class UserBean {
private String username;
private String userid;
private String userType;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType;
}
}
Now i want to use this bean in many of my dao methods. The problem i face is i have to modify my dao parameters to include this bean info which i think will not be a good design.
How can i include UserBean Details without modifying my DAO methods ?
I am using spring MVC 3

I think it is not a good idea to access web context classes in your DAO, this will introduce a tight coupling among the layers and changing something in the presentation layer might effect your DAO layer objects. You can pass this information to your DAO classes as a method parameter instead.
But if you really want to get access to session attributes in your DAO, you can use RequestContextHolder for this:
ServletRequestAttributes request = (ServletRequestAttributes) RequestContextHolder
.currentRequestAttributes();
HttpSession session = request.getRequest().getSession();
UserBean UserBean = (UserBean)session.getAttribute("userBean");
As you are referring to request attributes outside of an actual web request, you need to add RequestContextListener to your web.xml to expose the current request:
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

DAO layer should not be aware of the web session.
Implement session related logic in 'upper' layer, in manager or service.
In your 'refactoring' case it would have an added benefit of acting as an adapter between Spring MVC layer and DAO, beside being good design.

You can create an instance variable in your DAO class and one setter and getter for that.
But before calling any DAO method you have to set userBean in that DAO which is again not good practice but may be one of the solution.

You could define UserBean as a Spring bean and use Spring's session scope. E.g.:
<bean id="user" class="com.foo.UserBean" scope="session">
<aop:scoped-proxy/>
</bean>
<bean id="userDao" class="com.foo.UserDao">
<property name="user" ref="user"/>
</bean>
For documentation, see 3.5.4.5 Scoped beans as dependencies in the Spring documentation.

Related

MVC design - Can I have domain model validation in the Controller class?

The following is just an exmaple for context not the actual implementation. Using Spring MVC, I have the following Model which has validation based on annotations.
#Entity
public class Customer {
#Id private int id;
#NotNull private String name;
}
And the following DTO used to map the data received in the request's body in the Controller's createNewCustomer function.
public class CustmerDTO{
private String name;
}
In my Controller I am using the modelMapper to convert the customerDTO to a new domain model Customer object. Based on the #NotNull annotation, if the name property of the recieved object (customerDTO) is empty the ConstraintViolationException is thrown.
public class CustomerController {
#Autowired private CustomerService customerService;
#Autowired private ModelMapper modelMapper;
#PostMapping(value = "/customer")
public Customer createNewCustomer (#RequestBody CustomerDTO customerDTO) {
try {
Customer newCustomer = modelMapper.map(customerDTO, Customer.class);
return customerService.saveCustomer(newCustomer);
}
catch (ConstraintViolationException e) {
throw new CustomerMissingInformation();
}
}
}
As you can see here I handle validation for the Customer in the Controller, which by definition is not a good habit, as Controllers in MVC are part of the presentation layer, and should have no clue about how to perform data validation, also I want to keep my controllers as light as possible.
Can I keep this design or is there any good approach to move my validation in the Service layer while keeping validation annotations and also allowing the Controller to be able to receive representation objects(DTOs) and convert them to domain models?
Looking more into this, I came to the following conclusion. Validation for persisting an object should happen as soon as possible and at property level, as you don't want your persistence layer or any mappers that you might be using deal with null when it is not expected. Everything that goes past property validation, shall be approached from a contextual validation perspective, and be passed to methods that hold logic for a given context.
Is this order valid to be filled, is this customer valid to check in to the hotel. So rather than have methods like isValid have methods like isValidForCheckIn.

Store user info in spring environment

I get userId from request.getRemoteUser(), I want to store it somewhere and get from any layer of application. I don't want to pass the userId from controller to other layers or store it in context. Is there anything similar to this, so that simply autowired userId and use it anywhere.
I'm using Spring-boot and Spring-rest controller.
#Configuration
public class ConfigurationClass {
private #Value("#{ request.getRemoteUser() }") String userId;
#Bean("userId")
#Scope("request")
public String getUserId() {
return userId;
}

Can I place the #Transactional annotation to an entity class?

I am trying the Active Record pattern using Spring and Hibernate framework. Below is the description of this pattern:
An object carries both data and behavior. Much of this data is persistent and needs to be stored in a database. Active Record uses the most obvious approach, putting data access logic in the domain object. This way all people know how to read and write their data to and from the database.
So, I removed the traditional Service class and moved its logic and the #Transactional annotation to the entity class. But when I run my application again, the following exception was thrown.
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
org.springframework.orm.hibernate5.SpringSessionContext.currentSession(SpringSessionContext.java:133)
org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:454)
weibo.datasource.UserDao.save(UserDao.java:17)
weibo.domain.User.register(User.java:32)
weibo.web.UserController.register(UserController.java:29)
Source Code
The UserController class:
#PostMapping("/users/register")
public String register(#RequestParam("username") String username,
#RequestParam("password") String password) {
User user = new User(userDao, username, password);
user.register();
return "redirect:/users/login";
}
The User entity class:
#Entity
#Table(name="USERS")
#Transactional
public class User {
#Id
#GeneratedValue
private int id;
private String name;
private String password;
#Transient
private UserDao userDao;
public User() {}
public User(UserDao userDao, String username, String password) {
...
}
public void register() {
userDao.save(this);
}
}
The UserDao class. No #Transactional annotated.
public UserDao(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void save(User user) {
sessionFactory.getCurrentSession().save(user);
}
Why?
UPDATE
As #cristianhh said, the #Transactional annotation must be used in a Spring-Managed bean. However, the entity class is not.
No, while #Transactional is managed by Spring, #Entity is managed by Hibernate.
Hibernate beans are not managed by Spring and respectively not wrappable by the #Transactional annotation.
You can however, use #Transactional in the service/repository layer and wrap a function sending the entity's data access object (DAO).

how to set resource relations through annotations in Spring Hateoas?

Is there a way to set resource relations through annotations? I made a similar question a some time ago but i've not been clear enough. I want to have something like this:
public class UserResource {
private String username;
#Relation(value = "{servicebaseUrl}/classes/${value}", rel = "class")
private String classId;
// Getters and setters
}
And then add a message converter which would add links only if client sends Accept = application/hal+json, avoiding the fact of doing two different controller endpoints for application/hal+json and application/json. Does Spring offers something like that? I found that it actually offers this #Relation annotation(or similar one) but it seems that it is not for the same purposes.
No this is not possible - you would have to implement a ResourceAssembler to add links to your resources.
Usually your resources extend ResourceSupport.
class PersonResource extends ResourceSupport {
String firstname;
String lastname;
}
Then your create ResourceAssembler to control the creation of that resource:
class PersonResourceAssembler extends ResourceAssemblerSupport<Person, PersonResource> {
public PersonResourceAssembler() {
super(PersonController.class, PersonResource.class);
}
#Override
public PersonResource toResource(Person person) {
PersonResource resource = createResource(person);
// … do further mapping and add links
resource.add(new Link("http://myhost/people"));
return resource;
}
}
See the spring hateoas documentation for details

managing public and private information of entities in session beans?

I see a lot of examples where entity objects are returned or passed in session bean methods. But the concept of remote interfaces for session beans make me think that this is bad practice as the entity might hold private data. A client doing remote calls to a session bean shouldn't be able to access all data. I'm just confused? If not, how should I encounter this issue? Should I create classes shadowing the entities public properties?
Let's say I have an entity class for users as following:
#Entity
public class User implements Serializable {
private Integer id;
private String username;
private String email;
private String password;
...
}
For visitors using a java client accessing this entity through a session bean, I want only the id and the username be visible for them. The authenticated user should be able to access all properties expect the password property. Isn't unsafe to have a session bean like this:
#Stateless
public class UserManager {
public User getUserById(Integer id) {
...
}
public List<User> findUsers(String searchKey) {
...
}
}
How should one encounter such security problems?

Categories

Resources