@Inject to pass params to a CDI @Named bean via URL
This works only with the in JSF 2.3 introduced javax.faces.annotation.ManagedProperty
.
@Inject @ManagedProperty("#{param.id}")
private String id;
The now deprecated javax.faces.bean.ManagedProperty
annotation works only in JSF @ManagedBean
classes. I.e. in instances which are managed by JSF. It does not work in instances which are managed by CDI @Named
. Further, you've made another mistake: you're trying to prepare the Message
based on the managed property in the constructor. If it were a real @ManagedBean
, that would also not have worked. The managed property is not available during construction, simply because it's not possible to call the setter method before the constructor is called. You should have used a @PostConstruct
method for this.
If you cannot upgrade to JSF 2.3, you'd need to create a custom CDI annotation. A concrete example is posted in this blog. Here's an extract of relevance:
The custom @HttpParam
annotation:
@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface HttpParam {
@NonBinding
public String value() default "";
}
The annotation value producer:
public class HttpParamProducer {
@Inject
FacesContext facesContext;
@Produces
@HttpParam
String getHttpParameter(InjectionPoint ip) {
String name = ip.getAnnotated().getAnnotation(HttpParam.class).value();
if ("".equals(name)) name = ip.getMember().getName();
return facesContext.getExternalContext()
.getRequestParameterMap()
.get(name);
}
}
An usage example:
@Inject @HttpParam
private String id;
JSF utility library OmniFaces has a @Param
for exactly this purpose, with builtin support for JSF conversion and validation.
Alternatively, you can also manually grab the request parameter from the external context in the Detail
managed bean. The recommended way to do managed bean initialization is to use a @PostConstruct
method, not the constructor, as the constructor could be used for completely different purposes than managed bean creation:
@PostConstruct
public void init() {
String id = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id");
// ...
}
Another way, IMO also more suitable for this particular case, is to use <f:viewParam>
which also allows you to convert the ID to Message
directly by a custom converter.
<f:metadata>
<f:viewParam name="id" value="#{detail.message}" converter="messageConverter" />
</f:metadata>
with just
@Named
public class Detail {
private Message message;
// Getter+setter
}
and a
@FacesConverter("messageConverter")
public class MessageConverter implements Converter {
// Convert string id to Message object in getAsObject().
// Convert Message object to string id in getAsString().
}
See also
- ViewParam vs @ManagedProperty(value = "#{param.id}")
- Communication in JSF 2.0 - processing GET request parameters