Reputation: 2858
I'm trying to implement this simple example in JSF: There is a user.xhtml page which can be accessed with an id parameter (user.xhtml?id=3 / user.xhtml?id=12). Depending on the id The page should display the info of the user who has that specified id.
@ManagedBean
@RequestScoped
public class OverviewController extends BaseController{
private UserDetails details;
@PostConstruct
@SuppressWarnings("unused")
private void init(){
Integer userId = getIntegerParam(Constants.PARAMETER_USER); //this brings the value of the user parameter as an Integer
if (userId != null){
UserService userService = new UserService();
details = userService .getDetails(userId);
}
}
//GET & SET
}
In the xhtml file I have the followings:
<div>
Name: #{overviewController.details.name}
City: #{overviewController.details.city}
</div>
The link which guided the control here:
<h:link outcome = "user.xhtml" value = "details">
<f:param name = "user" value = "2">
</h:link>
I was under the impression that when accessing the overviewController via EL the ManagedBean will get Constructed and in the @PostConstruct the details would get initialised. But I get no results and the overviewController isn't even constructed. I'm going further with my question and I ask how can a search depending on multiple parameters or a sort can be implemented?
Upvotes: 0
Views: 2959
Reputation: 1108742
As to your concrete problem, your @PostConstruct
is incorrectly been declared private
instead of public
.
As to your concrete functional requirement, this is not entirely the right way. You need a <f:viewParam>
in the target page to set the user ID request parameter as an UserDetails
property in the backing bean.
user.xhtml
<f:metadata>
<f:viewParam id="param_id" name="id" value="#{overviewController.details}"
converter="userDetailsConverter" converterMessage="Bad request, unknown user"
required="true" requiredMessage="Bad request, use a link from within the system"
/>
</f:metadata>
<h:message for="param_id" />
UserDetailsConverter
@FacesConverter("userDetailsConverter")
public class UserDetailsConverter implements Converter {
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (!(value instanceof UserDetails) || ((UserDetails) value).getId() == null) {
return null;
}
return String.valueOf(((UserDetails) value).getId());
}
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value == null || !value.matches("\\d+")) {
return null;
}
UserDetails details = new UserService().getDetails(Integer.valueOf(value));
if (details == null) {
throw new ConverterException(new FacesMessage("Unknown user ID: " + value));
}
return details;
}
}
OverviewController
private UserDetails details; // Getter+setter
Upvotes: 1
Reputation: 14257
Well, I don't know how your method getIntegerParam
actually works, but I usually implement processing query parameters like this.
Edit: I'm not actually sure if the init()
would be really invoked after the userId
property is set (I usually invoked it directly from the setter), but it probably should as @PostConstruct
methods are invoked after dependencies are injected.
@ManagedBean
@RequestScoped
public class OverviewController extends BaseController {
@ManagedProperty("#{param['userId']}")
private String userId; // not sure if can automatically be parsed to Integer
private UserDetails details;
@PostConstruct
private void init() {
if (userId != null){
UserService userService = new UserService();
details = userService .getDetails(userId);
}
}
// getter & setter for userId
}
Upvotes: 0