I'm having this problem with passing on data between JSF beans.. What I want to do is when I login, pass the username to a next bean where I can use it. I have found many things about this but I can't get it to work in my project. What I've got is a UserService where I can manage my users. There's a method in here called getUsers(username). Now I'm trying to pass the username so I can retrieve my user-object.
xHtml:
<h:link outcome="changeProfile" value="Change profile">
<f:param name="username" value="#{userBean.username}" />
</h:link>
changeProfileBean:
#Component("changeProfile")
#ManagedBean
#RequestScoped
public class ChangeProfileBean implements Serializable {
private UserService userService;
private User user;
#ManagedProperty("#{param.username}")
private String username;
#PostConstruct
public void init(){
FacesContext facesContext = FacesContext.getCurrentInstance();
this.username = facesContext.getExternalContext().getRequestParameterMap().get("username");
try {
if(username != null){
user = userService.getUser(username);
}
} catch (UserServiceException e) {
e.printStackTrace();
}
}
#Autowired
public ChangeProfileBean(UserService userService) {
this.userService = userService;
}
What happens is that the changeUserbean will be created when the app is starting. And immediately after that runs the #PostConstruct where username obviously equals null. But when I call the changeUserBean it doesn't execute the #PostConstruct anymore..
Does anybody know what I could do?
UserBean:
#Component("userBean")
#Scope("session")
public class UserBean implements Serializable
{
#Autowired
private UserService userService;
#Autowired
private RepairService repairService;
private String username;
private String password;
While you have already the data you need in a broader scope, just inject that backing-bean into changeProfileBean:
#ManagedBean
#RequestScoped
public class ChangeProfileBean implements Serializable {
#ManagedProperty("#{userBean}")
private UserBean userBean;
public UserBean getUserBean(){
return userBean;
}
public void setUserBean(UserBean userBean){
this.userBean = userBean;
}
...
}
Related
I have this classes:
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
private UserRepository userRepository;
#Autowired
private BCryptPasswordEncoder passwordEncoder;
#Autowired
private EntityManager entityManager;
#Override
public UserDetails loadUserByUsername( String username) throws UsernameNotFoundException {
Optional<User> userOptional = userRepository.findUserByUsername(username);
User user = userOptional.orElseThrow(
()->new UsernameNotFoundException("Username not found in the database")
);
return new MyUserDetails(user);
}
public void saveUser(User user){
User newUser=new User();
newUser.setUsername(user.getUsername());
newUser.setPassword(passwordEncoder.encode(user.getPassword()));
newUser.setEnabled(true);
newUser.setRoles(List.of(entityManager.find(Role.class,1)
));
userRepository.save(newUser);
}
public void deleteUser(User user){
userRepository.delete(user);
}
public UserDetails getCurrentlyLoggedUser(Authentication authentication){
Object principal = authentication.getPrincipal();
if(principal instanceof UserDetails){
String username=((User) principal).getUsername();
UserDetails loggedUser = loadUserByUsername(username);
return loggedUser;
}
return null;
}}
#Controller
#RequiredArgsConstructor
public class OrderController {
private final OrderService orderService;
#Autowired
private final UserDetailsService userDetailsService;
#GetMapping("/orderlist")
public String showOrdeList(Model model, #AuthenticationPrincipal Authentication authentication){
userDetailsService.getCurrentlyLoggedUser
}
}
I want to know why the methods from UserDetailsServiceImpl class won't show up in the controller...
I can acces only the methods from the interface, but not the ones implemented besides them.
I tried to use qualifiers, and even made a config class to instantiate the impl class when injecting the bean by interface.
#Configuration
public class OrderConfig {
#Bean("userDetailsService")
public UserDetailsService userDetailsService() {
return new UserDetailsServiceImpl();
}
Can anyone tell me what I'm doing wrong?
Methods defined in UserDetailsServiceImpl but not in UserDetailsService aren't accessible because you're injecting your service by interface UserDetailsService and compiler doesn't know which implementation will be injected in runtime.
So, you need to define your own interface with all methods that you want to expose or inject your service by class.
#Autowired
private final UserDetailsServiceImpl userDetailsService;
I would recommend a custom interface that extends UserDetailsService and injecting your service using your custom interface.
I have a #SessionScope bean that keeps track of the current users role. When I run the application the value is present, however when I run my integration tests the bean is null.
Here's what I have:
#Component
#SessionScope
public UserSessionDataImpl implements UserSessionData {
private String role; // "Admin" or "User"
// getters/setters below
}
// Service
#Service("roleService")
public RoleServiceImpl implements RoleService {
#Autowired
UserSessionData sessionData;
public String getRole(){
return this.sessionData.getRole();
}
public String setRole(String role){
return this.sessionData.setRole(role);
}
}
// API
#Api
public class TicketApi {
#Autowired
private RoleService roleService;
#Autowired
private TicketService TicketService;
#RequestMapping(value = "person/{id}/tickets", method = RequestMethod.GET)
public String getTickets(long personId) {
// only admins can lookup tickets
if(roleService.getRoles.equals("Admin"){
// do logic
}
}
}
// Unit test method
#Before
public void setup(){
roleService.setRole("Admin"); //set role to admin for testing
}
#Test
// Calls TicketApi
public void getTicketsTest(){
mockMvc.perform(
get("/person/{id}/tickets")); // blows up due to null role
}
I am stumped as to why my roleSerivce loses the reference to sessionData. I do see that UserSessionDataImpl does get instantiated multiple times, which I wouldn't think would happen. I'm wondering if the mockMvc call creates a new Session which would cause the extra instantiations. Has anyone else figured this issue out?
I have a model in which I want to inject my service.
My Model
#Configurable
#Entity
#Table(name = "user")
public Class User {
#Autowired
private UserService userService;
{
System.out.println("Trying Service : " + userService.getMyName());
}
}
Here I get always a NullPointerException on 7'th line.
In my spring-context.xml I have :
<context:spring-configured/>
<bean
class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean
class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
EDIT
UserService
#Component
public Class UserService {
public String getMyName() { return "it's Me!";}
}
Spring managed components can be wired only into another beans managed by Spring.
However, there is a trick to add service to your POJO if you really need it:
Add UserService as a static field to your POJO with a setter
In UserService after spring initializes the bean, set itself as a field on the POJO (this can be done in #PostConstruct method)
Make a static instance of UserService available:
#Service
public Class UserService {
private static UserService instance;
public static UserService getInstance() { return instance; }
#PostConstruct
void init() { instance = this; }
public String getMyName() { return "it's Me!";}
}
call with:
UserService.getInstance().getMyName()
In the applicationContext file I have added the package to map it.
The call arrives, but the variable is still null and does not pass to the server. In other classes, the same is working correctly.
Thanks in advance!
#ManagedBean(name="registerUser")
#SessionScoped
public class RegisterUser{
#ManagedProperty("#{userService}")
private DAOUser userService;
private User user = new User();
public DAOUser getUserService() {
return userService;
}
public void setUserService(DAOUser userService) {
this.userService = userService;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String register() {
// Calling Business Service
String passwordEncripada = PasswordControl.encriptString(user.getPassword());
user.setPassword(passwordEncripada);
userService.register(user);
// Add message
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage("Registro realizado"));
return "";
}
and DAOUser class:
#Component
public class DAOUser implements Serializable {
#Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
#Transactional
public void register(User user){
// Acquire session
Session session = sessionFactory.getCurrentSession();
// Save employee, saving behavior get done in a transactional manner
session.save(user);
}
}
EDIT: The setter is called, but the object it sends is null
I think the problem was in the normalization of the DAOUser class name. I have gone to use #Repository ("userService") instead of #Component and it is already working.
#Repository("userService")
public class DAOUser implements Serializable {
#Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
#Transactional
public void register(User user){
// Acquire session
Session session = sessionFactory.getCurrentSession();
// Save employee, saving behavior get done in a transactional manner
session.save(user);
}
}
I've developed a Spring Web-MVC application. I have some offices in my project. Each user belongs to an office. user.getOfficeType() returns an integer representing the user's office type. If the office type is 1, the user belongs to Office1 and etc.
However I want to inject the authenticated user's office into my service classes:
class MyService{
#Autowired
Office currentOffice;
...
}
I read the Spring docs. I need a session scoped bean to inject it into my service classes.
applicationContext.xml:
<mvc:annotation-driven />
<tx:annotation-driven transaction-manager="hibernateTransactionManager"/>
<context:annotation-config />
<context:component-scan base-package="com.package.controller" />
<context:component-scan base-package="com.package.service" />
...
<bean id="office" class="com.package.beans.Office" scope="session">
<aop:scoped-proxy/>
</bean>
I have three implementations of the Office interface. Once a user requests a resource, I want to be aware of his Office. So I need to inject his session-scoped Office into my service classes. But I don't know how to instantiate it according to the user's office. please help!
I found a solution! I declared an OfficeContext that wraps the Office and also implements it.
#Component
#Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class OfficeContext implements InitializingBean, Office {
private Office office;
#Autowired
private UserDao userDao;
#Autowired
private NoneOffice noneOffice;
#Autowired
private AllOffice allOffice;
#Autowired
private TariffOffice tariffOffice;
#Autowired
private ArzeshOffice arzeshOffice;
public Office getOffice() {
return this.office;
}
#Override
public void afterPropertiesSet() throws Exception {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth.isAuthenticated()) {
String name = auth.getName(); //get logged in username
JUser user = userDao.findByUsername(name);
if (user != null) {
this.office = noneOffice;
} else {
OfficeType type = user.getOfficeType();
switch (type) {
case ALL:
this.office = allOffice;
break;
case TARIFF:
this.office = tariffOffice;
break;
case ARZESH:
this.office = arzeshOffice;
break;
default:
this.office = noneOffice;
}
}
} else {
this.office = noneOffice;
}
}
#Override
public OfficeType getType() {
return office.getType();
}
#Override
public String getDisplayName() {
return office.getDisplayName();
}
}
and in my service classes I injected the OfficeContext.
#Service
public class UserService {
#Autowired
UserDao userDao;
#Autowired
OfficeContext office;
public void persist(JUser user) {
userDao.persist(user);
}
public void save(JUser user) {
userDao.save(user);
}
}
I'm just throwing a different approach
#Configuration
public class SessionScopeBeansConfig {
#Bean
#SessionScope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public User user( UserDAO userDAO ) {
return userDAO.getUserByLoginName( SecurityContextHolder.getContext().getAuthentication().getName() );
}
#Bean
#SessionScope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public Office office( User user ) {
Office office = <<Code to initialize office>>;
return office;
}
}
This way it's possible to directly inject the Office
class MyService{
#Autowired
Office currentOffice;
...
}