Remeber from the Inject a Java logger via a CDI producer method post that the InjectionPoint can be used to access metadata of the class where the artifact is injected. Based on this statement, we can write a producer method capable to inject HTTP parameters.
Typically, as a JSF developer you write a form like below:
<h:form>
Name: <h:inputText value="#{playerBean.name}"/>
Surname: <h:inputText value="#{playerBean.surname}"/>
<h:commandButton value="Register" action="#{playerBean.registerAction()}"/>
</h:form>
The two fields, nameand surname are declared in a bean privateand with some getters and setters:
@Named
@RequestScoped
public class PlayerBean {
private static final Logger LOG = Logger.getLogger(PlayerBean.class.getName());
private String name;
private String surname;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public void registerAction() {
LOG.info("Register: " + name + "" + surname);
}
}
Well, nothing fancy here, and even a JSF novice can understand what this code do just by looking over it in a second. But, now let's replace the <h:inputText/>with simple HTML <input/>as below:
<h:form>
Name: <input type="text" name="name" id="name"/>
Surname: <input type="text" name="surname" id="surname"/>
<h:commandButton value="Register" action="#{playerBean.registerAction()}"/>
</h:form>
This time our getters and setters become useless, but we can still obtain these two HTTP parameters like this:
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
ServletRequest request = (ServletRequest) externalContext.getRequest();
request.getParameter("name");
request.getParameter("surname");
Now, let's generalize this case in CDI style. Instead of writing request.getParameter("name"); we want to inject the HTTP parameter. For this, we start by defining a qualifier and instruct the container to ignore the value:
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface HttpParam {
@Nonbinding public String value();
}
Furthermore, we write the producer method as below - instead of explicitly nominated the HTTP parameter name, we use the InjectionPoint metadata features:
public class HttpParams {
@Produces
@HttpParam("")
String getParamValue(InjectionPoint ip) {
// obtain the current request
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
ServletRequest request = (ServletRequest) externalContext.getRequest();
// obtain the desired parameter
Annotated annotated = ip.getAnnotated();
HttpParam httpParam = annotated.getAnnotation(HttpParam.class);
return request.getParameter(httpParam.value());
}
}
Finally, we adjust the PlayerBeanto inject the desired HTTP parameters:
@Named
@RequestScoped
public class PlayerBean {
private static final Logger LOG = Logger.getLogger(PlayerBean.class.getName());
@HttpParam("name") @Inject String name;
@HttpParam("surname") @Inject String surname;
public void registerAction() {
LOG.log(Level.INFO, "Register: {0} {1}", new Object[]{name, surname});
}
}
Done! Following this example you can inject any other HTTP parameter. The complete example is available here.
Now, you can use this with <f:param/> or in place of <f:event type="preRenderView/> or <f:viewAction/>. In addition, you may be interested in converting and validating the HTTP parameters. Check out a great implementation from OmniFaces which is materialized in the CDI annotation @Param that allows us to inject, convert and validate a HTTP request parameter in a CDI managed bean.
Now, you can use this with <f:param/> or in place of <f:event type="preRenderView/> or <f:viewAction/>. In addition, you may be interested in converting and validating the HTTP parameters. Check out a great implementation from OmniFaces which is materialized in the CDI annotation @Param that allows us to inject, convert and validate a HTTP request parameter in a CDI managed bean.