How to pass the ID of the current user rendered on the page to an action handler method in JSF 2?
I have a JSF page in which I show the details of a given user:
<h:form>
<p>
<h:outputLabel value="User Name" for="userName" />
<h:outputText id="userName" value="#{userController.user.name}" />
</p>
<p>
<h:outputLabel value="Email" for="email" />
<h:outputText id="email" value="#{userController.user.email}" />
</p>
<p>
<h:commandLink value="Edit" action="#{userController.edit(userController.user.id)}" />
</p>
</h:form>
This works fine with the exception of the Edit commandLink. When I click it, I expect userController.edit
to be passed the ID of the user that's currently being rendered on the page.
However looks like as userController
is a request scoped bean that has a @PostConstruct
method that assigns a new User to the user field, always 0 is being passed to the action method as the ID of a new instance of User is null
which apparently gets converted to 0.
How can I fix this controller/page, without changing the scope of the controller, to pass the correct ID to the edit action? Here's the code for the controller:
@Model
public class UserController {
@Inject
@UserRepository
private EntityManager entityManager;
@Inject
private UserTransaction tx;
private User user;
public String edit(Long id) {
System.out.println("id = " + id);
// fetch the user with id from the db
return "edit";
}
public User getUser() {
return user;
}
public void setUser(User user)开发者_开发知识库 {
this.user = user;
}
@PostConstruct
private void init() {
user = new User();
}
}
The approach is weird but I can imagine when you need this. (e.g. you don't wand to write to session and flash scope don't work in distributed environment etc.). BTW if you can't use session scope consider using flash scope.
Apart from correctness of the approach, try adding aditional field to the bean:
protected Long currentId;
public Long getCurrentId() {
return currentId == null ? user.getId() : currentId;//or simply return it, I don't know how you play with the user field
}
public void setCurrentId(Long currentId) {
this.currentId = currentId;
}
Remove parameter from edit
action and use currentId
field, and to your view add param (hidden field will not work here):
<f:viewParam name="id" value="#{userController.currentId}" />
Then in action you can get user id from the previous view simply accessing this.currentId. And BTW, try load your User from another place, not int @PostConstruct. If you create user in @PostConstruct then when you are in edit method the currentId will be from previous view, and user.id will be from @PostConstruct. So if you don't want to store user in session scope, but use only request scope you have to persist it immediately after creation (e.g. in database). In edit method you have to get it back using currentId.
精彩评论