My JSF Books/Videos My JSF Tutorials OmniFaces/JSF PPTs
JSF 2.3 Tutorial
JSF Caching Tutorial
JSF Navigation Tutorial
JSF Scopes Tutorial
JSF Page Author Beginner's Guide
OmniFaces 2.3 Tutorial Examples
OmniFaces 2.2 Tutorial Examples
JSF Events Tutorial
OmniFaces Callbacks Usages
JSF State Tutorial
JSF and Design Patterns
JSF 2.3 New Features (2.3-m04)
Introduction to OmniFaces
25+ Reasons to use OmniFaces in JSF
OmniFaces Validators
OmniFaces Converters
JSF Design Patterns
Mastering OmniFaces
Reusable and less-verbose JSF code

My JSF Resources ...

Java EE Guardian
Member of JCG Program
Member MVB DZone
Blog curated on ZEEF
OmniFaces is an utility library for JSF, including PrimeFaces, RichFaces, ICEfaces ...

[OmniFaces Utilities] - Find the right JSF OmniFaces 2 utilities methods/functions

Search on blog

Petition by Java EE Guardians

Twitter

joi, 16 iunie 2016

CDI-JSF: Injecting HTTP parameters via a producer method

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, name and surname are declared in a bean private and 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 PlayerBean to 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. 

Niciun comentariu :

Trimiteți un comentariu

JSF BOOKS COLLECTION

Postări populare

Follow by Email

Visitors Starting 4 September 2015

Locations of Site Visitors