跳至主要内容

JSF 2.3 : Injection supports in Converter, Validator and Behavior

Injection supports in Converter, Validator and Behavior

In JSF 2.3, Converter, Validator and Behavior are refactored to generic interfaces.
Have a look at the Converter interface.
public interface Converter<T> {

    public T getAsObject(FacesContext context, UIComponent component,
                              String value);

    public String getAsString(FacesContext context, UIComponent component,
                              T value);  
}
And these interfaces also support @Inject and also can be injected into other beans, which are originally planned in JSF 2.2, but delayed to be implemented in JSF 2.3.
Let's create a simple sample to taste it. TagsConverter is used to convert tag string to a tag list in backing bean.
@FacesConverter(value = "tagsConverter", managed = true)
public class TagsConverter implements Converter<List<String>> {
    
    @Inject
    ConverterUtils utils;

    @Override
    public List<String> getAsObject(FacesContext context, UIComponent component, String value) {
       return utils.stringToList(value);
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, List<String> value) {
       return utils.listToString(value);
    }

}
managed = true indicates the converter is a CDI managed converter.
To demonstrate @Inject supports in Converter, I extracted the conversion handling process into a CDI bean ConverterUtils, and inject it in TagsConverter.
@ApplicationScoped
public class ConverterUtils {

    @Inject
    Logger LOG;

    public String listToString(List<String> value) {
        LOG.log(Level.INFO, "listToString:{0}", value);
        return value != null ? join(",", value) : "";
    }

    public List<String> stringToList(String value) {
        LOG.log(Level.INFO, "stringToList:{0}", value);
        return value != null ? Arrays.asList(value.split(",")) : Collections.<String>emptyList();
    }

}
Now you can apply this converter on an input field in a facelets template.
 <div>
 <h:outputLabel for="tags" value="Tags" />
 <h:inputText 
  id="tags" 
  value="#{backingBean.tags}">
  <f:converter converterId="tagsConverter" />
 </h:inputText>    
</div>
The backingBean code is:
@RequestScoped
@Named
public class BackingBean {


    List<String> tags = new ArrayList<>();


    public List<String> getTags() {
        return tags;
    }

    public void setTags(List<String> tags) {
        this.tags = tags;
    }

   

}
And the TagsConverter can be injected into other beans like other generic CDI beans.
@RequestScoped
@Named
public class BackingBean {

    @Inject
    @FacesConverter(value="tagsConverter", managed = true)
    TagsConverter mytagsConverter;
 
 List<String> mytags = new ArrayList<>();
 
 public List<String> getMytags() {
        return mytags;
    }

    public void setMytags(List<String> mytags) {
        this.mytags = mytags;
    }

//...

}
In the facelets template, we can bind it to the converter directly.
<div>
 <h:outputLabel for="mytags" value="My Tags" />
 <h:inputText 
  id="mytags" 
  value="#{backingBean.mytags}">
  <f:converter binding="#{backingBean.mytagsConverter}"/>
 </h:inputText>     
</div>
Let's run this sample on Glassfish v5, open browser and navigate to http://localhost:8080/jsf-converter/converter.faces.
jsf converter
Grab the source codes from my github account, and have a try.

评论

此博客中的热门博文

Build a Reactive application with Angular 5 and Spring Boot 2.0

I have created a post to describe Reactive programming supports in Spring 5 and its subprojects, all codes of this article are updated the latest Spring 5 RELEASE, check spring-reactive-sample under my Github account.
In this post, I will create a simple blog system, including:
A user can sign in and sign out.An authenticated user can create a post.An authenticated user can update a post.Only the user who has ADMIN role can delete a post.All users(including anonymous users) can view post list and post details.An authenticated user can add his comments to a certain post. The backend will be built with the latest Spring 5 reactive stack, including:
Spring Boot 2.0, at the moment the latest version is 2.0.0.M7Spring Data MongoDB supports reactive operations for MongoDBSpring Session adds reactive support for WebSessionSpring Security 5 aligns with Spring 5 reactive stack The frontend is an Angular based SPA and it will be generated by Angular CLI.
The source code is hosted on Github, …

Activating CDI in JSF 2.3

Activating CDI in JSF 2.3 When I upgraed my Java EE 7 sample to the newest Java EE 8, the first thing confused me is the CDI beans are not recoganized in Facelects template in a JSF 2.3 based web applicaiton, which is working in the development version, but in the final release version, they are always resolved as null. I filed an issue on Mojarra and discussed it with the developers from communities and the JSF experts.
According to the content of README, In a JSF 2.3 application, to activate CDI support, declaring a 2.3 versioned faces-config.xml and adding javax.faces.ENABLE_CDI_RESOLVER_CHAIN in web.xml is not enough, you have to declare @FacesConfig annotated class to enable CDI.
Here is the steps I created a workable JSF 2.3 applicatoin in Java EE 8.
Create a Java web application, this can be done easily by NetBeans IDE, or generated by Maven archetype, for exmaple.
$ mvn archetype:generate -DgroupId=com.example -DartifactId=demo -DarchetypeArtifactId=maven-archetype-w…

JSF 2.3:Websocket support

Websocket support One of the most attractive features is JSF 2.3 added native websocket support, it means you can write real-time applications with JSF and no need extra effort.
To enable websocket support, you have to add javax.faces.ENABLE_WEBSOCKET_ENDPOINT in web.xml.
<context-param> <param-name>javax.faces.ENABLE_WEBSOCKET_ENDPOINT</param-name> <param-value>true</param-value> </context-param> Hello Websocket Let's start with a simple example.
@ViewScoped@Named("helloBean") publicclassHelloBeanimplementsSerializable { privatestaticfinalLoggerLOG=Logger.getLogger(HelloBean.class.getName()); @Inject@PushPushContext helloChannel; String message; publicvoidsendMessage() { LOG.log(Level.INFO, "send push message"); this.sendPushMessage("hello"); } privatevoidsendPushMessage(Objectmessage) { helloChannel.send(""+ message +" at &…