Inject support in Converter, Validator and Behavor
In JSF 2.3, Converter, Validator and Behavior are refactored to generic interfaces.
Have a look at the Converter interface.
1
public interface Converter<T> {
2
3
public T getAsObject(FacesContext context, UIComponent component,
4
String value);
5
6
public String getAsString(FacesContext context, UIComponent component,
7
T value);
8
}
Copied!
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.
1
@FacesConverter(value = "tagsConverter", managed = true)
2
public class TagsConverter implements Converter<List<String>> {
3
4
@Inject
5
ConverterUtils utils;
6
7
@Override
8
public List<String> getAsObject(FacesContext context, UIComponent component, String value) {
9
return utils.stringToList(value);
10
}
11
12
@Override
13
public String getAsString(FacesContext context, UIComponent component, List<String> value) {
14
return utils.listToString(value);
15
}
16
17
}
Copied!
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.
1
@ApplicationScoped
2
public class ConverterUtils {
3
4
@Inject
5
Logger LOG;
6
7
public String listToString(List<String> value) {
8
LOG.log(Level.INFO, "listToString:{0}", value);
9
return value != null ? join(",", value) : "";
10
}
11
12
public List<String> stringToList(String value) {
13
LOG.log(Level.INFO, "stringToList:{0}", value);
14
return value != null ? Arrays.asList(value.split(",")) : Collections.<String>emptyList();
15
}
16
17
}
Copied!
Now you can apply this converter on an input field in a facelets template.
1
<div>
2
<h:outputLabel for="tags" value="Tags" />
3
<h:inputText
4
id="tags"
5
value="#{backingBean.tags}">
6
<f:converter converterId="tagsConverter" />
7
</h:inputText>
8
</div>
Copied!
The backingBean code is:
1
@RequestScoped
2
@Named
3
public class BackingBean {
4
5
6
List<String> tags = new ArrayList<>();
7
8
9
public List<String> getTags() {
10
return tags;
11
}
12
13
public void setTags(List<String> tags) {
14
this.tags = tags;
15
}
16
17
18
19
}
Copied!
And the TagsConverter can be injected into other beans like other generic CDI beans.
1
@RequestScoped
2
@Named
3
public class BackingBean {
4
5
@Inject
6
@FacesConverter(value="tagsConverter", managed = true)
7
TagsConverter mytagsConverter;
8
9
List<String> mytags = new ArrayList<>();
10
11
public List<String> getMytags() {
12
return mytags;
13
}
14
15
public void setMytags(List<String> mytags) {
16
this.mytags = mytags;
17
}
18
19
//...
20
21
}
Copied!
In the facelets template, we can bind it to the converter directly.
1
<div>
2
<h:outputLabel for="mytags" value="My Tags" />
3
<h:inputText
4
id="mytags"
5
value="#{backingBean.mytags}">
6
<f:converter binding="#{backingBean.mytagsConverter}"/>
7
</h:inputText>
8
</div>
Copied!
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.
Last modified 8mo ago
Copy link