cannot use values from beans in facelets custom component - java

i cannot use any bean value in my custom control.:
for instance:
this is my foo.taglib.xml file.
<facelet-taglib>
<namespace>http://www.penguenyuvasi.org/tags</namespace>
<tag>
<tag-name>test</tag-name>
<component>
<component-type>test.Data</component-type>
</component>
</tag>
</facelet-taglib>
faces-config.xml
<component>
<component-type>test.Data</component-type>
<component-class>test.Data</component-class>
</component>
test.Data class
package test;
import java.io.IOException;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
public class Data extends UIComponentBase {
private Object msg;
#Override
public String getFamily() {
return "test.Data";
}
#Override
public void encodeBegin(FacesContext context) throws IOException {
super.encodeBegin(context);
context.getResponseWriter().write(msg.toString());
}
public void setMsg(Object msg) {
this.msg = msg;
}
}
Bean.java:
package test;
public class Bean {
private String temp = "vada";
public String getTemp() {
return temp;
}
}
test.xhtml (doesn't work)
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://www.penguenyuvasi.org/tags">
<py:test msg="#{bean.temp}" />
</html>
test.xhtml (works)
<py:test msg="#{bean.temp}" />

In your test.Data class, I suggest that you implement the getter for msg like that:
public String getMsg() {
if (msg != null) {
return msg;
}
ValueBinding vb = getValueBinding("msg");
if (vb != null) {
return (String) vb.getValue(getFacesContext());
}
return null;
}
And then, in your encodeBegin method:
...
context.getResponseWriter().write(getMsg());
...
This getter method is needed in order to evaluate the expression you may give to the msg attribute in your JSF page.
Edit, to use ValueExpression instead of the deprecated ValueBinding:
ValueExpression ve = getValueExpression("msg");
if (ve != null) {
return (String) ve.getValue(getFacesContext().getELContext());
}

Related

JSF Order of operations, should converters be applied before validators?

Are JSF converters supposed to be applied before validators? We have a situation where it seems it's being applied before the converter.
<o:importConstants
type="com.xxx.enums.UsState"
var="UsState" />
<b:selectOneMenu
id="homeStateSelectOneMenu"
value="#{contactPage.contact.homeState}"
label="Home State"
converter="DisplayableTextConverter">
<f:selectItem
id="selectOneUsStateSelectItem"
itemLabel="Select One"
noSelectionOption="true"
itemDisabled="true" />
<f:selectItems
id="usStateSelectItems"
value="#{UsState}" />
</b:selectOneMenu>
and the model object has this field:
#Enumerated(EnumType.STRING)
#Column(name = "home_state")
#NotNull //LYNCHPIN
private UsState homeState;
Converter:
#ApplicationScoped
#FacesConverter(value = "DisplayableTextConverter", managed = true)
public class DisplayableTextConverter implements Converter<DisplayableText> {
public static final String STATE_KEY = "DisplayableTextConverter.forClass";
#SuppressWarnings("unchecked")
#Override
public DisplayableText getAsObject(final FacesContext context, final UIComponent component, String text) {
text = trimToNull(text);
if (text != null) {
final String className = (String) component.getTransientStateHelper().getTransient(STATE_KEY);
try {
return DisplayableText.parseEnum(text, (Class<DisplayableText>) Class.forName(className));
} catch (final ClassNotFoundException e) {
throw new RuntimeException(e);
}
} else {
return null;
}
}
#Override
public String getAsString(final FacesContext context, final UIComponent component, final DisplayableText displayableText) {
if (displayableText != null) {
component.getTransientStateHelper().putTransient(STATE_KEY, displayableText.getClass().getName());
return displayableText.getDisplayText();
} else {
return null;
}
}
}
Enum: (truncated)
public enum UsState implements DisplayableText {
AL("Alabama"), AK("Alaska"), AZ("Arizona"), AR("Arkansas"), ....
public final String displayText;
#Override
public String getDisplayText() {
return displayText;
}
UsState(String specificDisplayValue) {
displayText = specificDisplayValue;
}
}
So what's interesting is if we remove #NotNull, the form submits, and if we add it, the submission fails. Looking at the stack trace, it appears that when the #NotNull it appears the validator is being called before the converter in certain cases. Why would this be?
Here is No #NotNull:
java.lang.IllegalArgumentException: Arkansas is not an instance of class com.xxx.UsState
at org.apache.bval.jsr.job.ValidateProperty.<init>(ValidateProperty.java:515)
at org.apache.bval.jsr.job.ValidationJobFactory.validateValue(ValidationJobFactory.java:76)
at org.apache.bval.jsr.ValidatorImpl.validateValue(ValidatorImpl.java:65)
at org.apache.bval.jsr.CascadingPropertyValidator.validateValue(CascadingPropertyValidator.java:99)
at javax.faces.validator.BeanValidator.validate(BeanValidator.java:218)
at javax.faces.component._ComponentUtils.callValidators(_ComponentUtils.java:291)
at javax.faces.component.UIInput.validateValue(UIInput.java:489)
at net.bootsfaces.component.selectOneMenu.SelectOneMenu.validateValue(SelectOneMenu.java:118)
at net.bootsfaces.component.selectOneMenu.SelectOneMenuRenderer.decode(SelectOneMenuRenderer.java:96)
at javax.faces.component.UIComponentBase.decode(UIComponentBase.java:479)
at javax.faces.component.UIInput.decode(UIInput.java:371)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1408)
at javax.faces.component.UIInput.processDecodes(UIInput.java:207)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1402)
at javax.faces.component.UIForm.processDecodes(UIForm.java:154)
at org.apache.myfaces.context.servlet.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:775)
and here is without the #NotNull (breakpoint in DisplayableTextConverter):
at com.xxx.jsf.converter.DisplayableTextConverter.getAsObject(DisplayableTextConverter.java:21)
at com.xxx.jsf.converter.DisplayableTextConverter.getAsObject(DisplayableTextConverter.java:1)
at org.apache.myfaces.cdi.converter.FacesConverterCDIWrapper.getAsObject(FacesConverterCDIWrapper.java:63)
at net.bootsfaces.render.CoreRenderer.getConvertedValue(CoreRenderer.java:532)
at javax.faces.component.UIInput.getConvertedValue(UIInput.java:789)
at javax.faces.component.UIInput.validate(UIInput.java:708)
at javax.faces.component.UIInput.processValidators(UIInput.java:293)
at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1458)
at javax.faces.component.UIForm.processValidators(UIForm.java:210)
at org.apache.myfaces.context.servlet.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:779)
Thanks! This is running on Apache TomEE 8.0.6 but with MyFaces 2.3.8, Bootsfaces 1.5.0

How to display java.time.LocalDate (Java 8) in Spring MVC 4 JSP [duplicate]

I haven't been able to figure out how to display a java.time.LocalDate value in a JSP.
In my JSP, I have this:
<fmt:formatDate value="${std.datum}" type="date" pattern="dd.MM.yyyy" var="stdDatum" />
The std.datum is of type java.time.LocalDate. When rendering the JSP I get this exception:
javax.el.ELException:
Cannot convert 2015-02-14 of type class
java.time.LocalDate to class java.util.Date
I'm assuming it's the conversion?
So is it possible to format an instance of LocalDate class with <fmr:formatDate> action?
I'm assuming it's the conversion?
Yes, it's a conversion related exception.
Solution
You could first use the <fmt:parseDate> action from the JSTL's "I18n capable formatting tag library" to do the conversion and then do the formatting with the <fmt:formatDate> action.
Here is an example:
<fmt:parseDate value="${std.datum}" type="date" pattern="yyyy-MM-dd" var="parsedDate" />
<fmt:formatDate value="${parsedDate}" type="date" pattern="dd.MM.yyyy" var="stdDatum" />
This solution is also presented right in the "JavaServer Pages™ Standard Tag Library (JSTL)" specification version 1.2 (see page 109).
This is an old question, but i find it is very best to do a custom tld in this case: without any double conversion to and from String.
Do your own tld file, then override the FormatDate class. Finally, declare your own custom prefix and use custom:formatDate instead of fmt:formatDate.
here is a simplified version
usage in JSP:
<%# taglib uri="/WEB-INF/custom" prefix="custom" %>
...
<custom:formatDate value="${std.datum}" pattern="dd/MM/yyyy" />
WEB-INF/custom.tld file
<?xml version="1.0" encoding="UTF-8"?>
<tag ib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd">
<tag>
<description>
FormatDate with java8 type
</description>
<name>formatDate</name>
<tag-class>com.custom.tag.FormatDateTag</tag-class>
<body-content>empty</body-content>
<attribute>
<description>
Date and/or time to be formatted.
</description>
<name>value</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<description>
Custom formatting style for dates and times.
</description>
<name>pattern</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
Then the java class tag file
public class FormatDateTag extends TagSupport {
protected Temporal value;
protected String pattern;
private String var;
private int scope;
public FormatDateTag()
{
super ();
init ();
}
private void init()
{
this.pattern = this.var = null;
this.value = null;
this.scope = PageContext.PAGE_SCOPE;
}
public void setVar(final String var)
{
this.var = var;
}
public void setScope(final String scope)
{
this.scope = Util.getScope (scope);
}
public void setValue(final Temporal value)
{
this.value = value;
}
public void setPattern(final String pattern)
{
this.pattern = pattern;
}
#Override
public int doEndTag() throws JspException
{
String formatted = null;
if (this.value == null)
{
if (this.var != null)
{
this.pageContext.removeAttribute (this.var, this.scope);
}
return EVAL_PAGE;
}
// Create formatter
if (this.pattern != null)
{
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern (this.pattern);
formatted = formatter.format (this.value);
}
else
{
// no formatting locale available, use Date.toString()
formatted = this.value.toString ();
}
if (this.var != null)
{
this.pageContext.setAttribute (this.var, formatted, this.scope);
}
else
{
try
{
this.pageContext.getOut ().print (formatted);
}
catch (final IOException ioe)
{
throw new JspTagException (ioe.toString (), ioe);
}
}
return EVAL_PAGE;
}
#Override
public void release()
{
init ();
}
}
I wanted to avoid changing all the places where <fmt:formatDate/> where used, so I created the following two classes in stead:
First, a converter to convert (some of) the java.time classes. It checks that java.util.Date is the target type, if not, it does nothing. It supports source time as java.util.Date (including java.sql.Timestamp and java.sql.Date), LocalDate, LocalDateTime, ZonedDateTime, Instant or Long (time in millis).
package com.example.elresolvers;
import javax.el.ELContext;
import javax.el.TypeConverter;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
#SuppressWarnings("UseOfObsoleteDateTimeApi")
public class DateFromJavaTimeResolver extends TypeConverter {
#Override
public Object convertToType(ELContext context, Object obj, Class<?> type) {
Date date = null;
if (Date.class.isAssignableFrom(type)) {
if (obj instanceof Date) {
date = (Date) obj;
} else {
ZonedDateTime zdt = null;
if (obj instanceof LocalDate) {
zdt = ((LocalDate) obj).atStartOfDay(ZoneId.systemDefault());
} else if (obj instanceof LocalDateTime) {
zdt = ((LocalDateTime) obj).atZone(ZoneId.systemDefault());
} else if (obj instanceof ZonedDateTime) {
zdt = (ZonedDateTime) obj;
} else if (obj instanceof Instant) {
date = Date.from((Instant) obj);
} else if (obj instanceof Long) {
date = new Date((Long) obj);
}
if (zdt != null) {
date = Date.from(zdt.toInstant());
}
}
context.setPropertyResolved(date != null);
}
return date;
}
}
Next, a ServletContextListener class to register the converter for use with JSP:
package com.example.web;
import com.example.elresolvers.DateFromJavaTimeResolver;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.jsp.JspApplicationContext;
import javax.servlet.jsp.JspFactory;
public class JspElResolverInitListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext servletContext = sce.getServletContext();
JspApplicationContext context = JspFactory.getDefaultFactory().getJspApplicationContext(servletContext);
context.addELResolver(new DateFromJavaTimeResolver());
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
Finally, an entry in web.xml (if you are not using annotations or other means):
<listener>
<listener-class>com.example.web.JspElResolverInitListener</listener-class>
</listener>
Java:
public class DateTimeUtil {
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy");
public static String toString(LocalDateTime ldt) {
return ldt.format(DATE_FORMATTER);
}
JSP:
<%# page import="ru.javaops.topjava.util.DateTimeUtil" %>
...
<%=DateTimeUtil.toString(std.getDatum())%>

Using java.time.LocalDate with JSTL <fmt:formatDate> action

I haven't been able to figure out how to display a java.time.LocalDate value in a JSP.
In my JSP, I have this:
<fmt:formatDate value="${std.datum}" type="date" pattern="dd.MM.yyyy" var="stdDatum" />
The std.datum is of type java.time.LocalDate. When rendering the JSP I get this exception:
javax.el.ELException:
Cannot convert 2015-02-14 of type class
java.time.LocalDate to class java.util.Date
I'm assuming it's the conversion?
So is it possible to format an instance of LocalDate class with <fmr:formatDate> action?
I'm assuming it's the conversion?
Yes, it's a conversion related exception.
Solution
You could first use the <fmt:parseDate> action from the JSTL's "I18n capable formatting tag library" to do the conversion and then do the formatting with the <fmt:formatDate> action.
Here is an example:
<fmt:parseDate value="${std.datum}" type="date" pattern="yyyy-MM-dd" var="parsedDate" />
<fmt:formatDate value="${parsedDate}" type="date" pattern="dd.MM.yyyy" var="stdDatum" />
This solution is also presented right in the "JavaServer Pages™ Standard Tag Library (JSTL)" specification version 1.2 (see page 109).
This is an old question, but i find it is very best to do a custom tld in this case: without any double conversion to and from String.
Do your own tld file, then override the FormatDate class. Finally, declare your own custom prefix and use custom:formatDate instead of fmt:formatDate.
here is a simplified version
usage in JSP:
<%# taglib uri="/WEB-INF/custom" prefix="custom" %>
...
<custom:formatDate value="${std.datum}" pattern="dd/MM/yyyy" />
WEB-INF/custom.tld file
<?xml version="1.0" encoding="UTF-8"?>
<tag ib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd">
<tag>
<description>
FormatDate with java8 type
</description>
<name>formatDate</name>
<tag-class>com.custom.tag.FormatDateTag</tag-class>
<body-content>empty</body-content>
<attribute>
<description>
Date and/or time to be formatted.
</description>
<name>value</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<description>
Custom formatting style for dates and times.
</description>
<name>pattern</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
Then the java class tag file
public class FormatDateTag extends TagSupport {
protected Temporal value;
protected String pattern;
private String var;
private int scope;
public FormatDateTag()
{
super ();
init ();
}
private void init()
{
this.pattern = this.var = null;
this.value = null;
this.scope = PageContext.PAGE_SCOPE;
}
public void setVar(final String var)
{
this.var = var;
}
public void setScope(final String scope)
{
this.scope = Util.getScope (scope);
}
public void setValue(final Temporal value)
{
this.value = value;
}
public void setPattern(final String pattern)
{
this.pattern = pattern;
}
#Override
public int doEndTag() throws JspException
{
String formatted = null;
if (this.value == null)
{
if (this.var != null)
{
this.pageContext.removeAttribute (this.var, this.scope);
}
return EVAL_PAGE;
}
// Create formatter
if (this.pattern != null)
{
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern (this.pattern);
formatted = formatter.format (this.value);
}
else
{
// no formatting locale available, use Date.toString()
formatted = this.value.toString ();
}
if (this.var != null)
{
this.pageContext.setAttribute (this.var, formatted, this.scope);
}
else
{
try
{
this.pageContext.getOut ().print (formatted);
}
catch (final IOException ioe)
{
throw new JspTagException (ioe.toString (), ioe);
}
}
return EVAL_PAGE;
}
#Override
public void release()
{
init ();
}
}
I wanted to avoid changing all the places where <fmt:formatDate/> where used, so I created the following two classes in stead:
First, a converter to convert (some of) the java.time classes. It checks that java.util.Date is the target type, if not, it does nothing. It supports source time as java.util.Date (including java.sql.Timestamp and java.sql.Date), LocalDate, LocalDateTime, ZonedDateTime, Instant or Long (time in millis).
package com.example.elresolvers;
import javax.el.ELContext;
import javax.el.TypeConverter;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
#SuppressWarnings("UseOfObsoleteDateTimeApi")
public class DateFromJavaTimeResolver extends TypeConverter {
#Override
public Object convertToType(ELContext context, Object obj, Class<?> type) {
Date date = null;
if (Date.class.isAssignableFrom(type)) {
if (obj instanceof Date) {
date = (Date) obj;
} else {
ZonedDateTime zdt = null;
if (obj instanceof LocalDate) {
zdt = ((LocalDate) obj).atStartOfDay(ZoneId.systemDefault());
} else if (obj instanceof LocalDateTime) {
zdt = ((LocalDateTime) obj).atZone(ZoneId.systemDefault());
} else if (obj instanceof ZonedDateTime) {
zdt = (ZonedDateTime) obj;
} else if (obj instanceof Instant) {
date = Date.from((Instant) obj);
} else if (obj instanceof Long) {
date = new Date((Long) obj);
}
if (zdt != null) {
date = Date.from(zdt.toInstant());
}
}
context.setPropertyResolved(date != null);
}
return date;
}
}
Next, a ServletContextListener class to register the converter for use with JSP:
package com.example.web;
import com.example.elresolvers.DateFromJavaTimeResolver;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.jsp.JspApplicationContext;
import javax.servlet.jsp.JspFactory;
public class JspElResolverInitListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext servletContext = sce.getServletContext();
JspApplicationContext context = JspFactory.getDefaultFactory().getJspApplicationContext(servletContext);
context.addELResolver(new DateFromJavaTimeResolver());
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
Finally, an entry in web.xml (if you are not using annotations or other means):
<listener>
<listener-class>com.example.web.JspElResolverInitListener</listener-class>
</listener>
Java:
public class DateTimeUtil {
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy");
public static String toString(LocalDateTime ldt) {
return ldt.format(DATE_FORMATTER);
}
JSP:
<%# page import="ru.javaops.topjava.util.DateTimeUtil" %>
...
<%=DateTimeUtil.toString(std.getDatum())%>

New annoying NPE on Yabe (Creating a custom editor)

I'm winding throught this Yabe tutorial and have been happily get bugs and solving them on my own.... until now.
in
http://localhost:9000/#documentation/guide9
This is the part about customizable edit window..
For whatever reason, when I post a new message, via
http://localhost:9000/admin/new
I receive a null pointer around tags...
In /app/controllers/Admin.java (around line 48)
44: post.content = content;
45: post.tags.clear();
46: }
47: //Set tags list
48: for(String tag : tags.split("\\s+")){
49: if(tag.trim().length() > 0) {
50: post.tags.add(Tag.findOrCreateByName(tag));
51: }
52: }
53: // Validate
54: validation.valid(post);
I looked at Admin.java and Tag.java and compared them line for line with the samples and tests copy. The only difference is an inclusion of validation on aAdmin.java for what I imagine is some test scripts written later down the road..
Any ideas?
here is my admin...
package controllers;
import play.*;
import play.mvc.*;
import java.util.*;
import models.*;
#With(Secure.class)
public class Admin extends Controller {
#Before
static void setConnectedUser() {
if(Security.isConnected()) {
User user = User.find("byEmail", Security.connected()).first();
renderArgs.put("user", user.fullname);
}
}
public static void index() {
List<Post> posts = Post.find("author.email", Security.connected()).fetch();
render(posts);
}
public static void form(Long id) {
if(id != null) {
Post post = Post.findById(id);
render(post);
}
render();
}
public static void save(Long id, String title, String content, String tags) {
Post post;
if(id == null) {
// Create post
User author = User.find("byEmail", Security.connected()).first();
post = new Post(author, title, content);
} else {
// Retrieve post
post = Post.findById(id);
post.title = title;
post.content = content;
post.tags.clear();
}
//Set tags list
for(String tag : tags.split("\\s+")){
if(tag.trim().length() > 0) {
post.tags.add(Tag.findOrCreateByName(tag));
}
}
// Validate
validation.valid(post);
if(validation.hasErrors()) {
render("#form", post);
}
//Save
post.save();
index();
}
}
here is my tag.java
package models;
import java.util.*;
import javax.persistence.*;
import play.db.jpa.*;
import play.data.validation.*;
#Entity
public class Tag extends Model implements Comparable<Tag> {
#Required
public String name;
private Tag(String name) {
this.name = name;
}
public static Tag findOrCreateByName(String name) {
Tag tag = Tag.find("byName", name).first();
if(tag == null) {
tag = new Tag(name);
}
return tag;
}
public static List<Map> getCloud() {
List<Map> result = Tag.find(
"select new map(t.name as tag, count(p.id) as pound) from Post p join p.tags as t group by t.name"
).fetch();
return result;
}
public String toString() {
return name;
}
public int compareTo(Tag otherTag) {
return name.compareTo(otherTag.name);
}
}
In the form that calls the save() method you might be missing an input with name 'tags'. Something like:
<input id="tags" name="tags" type="text" value="" />
In the tutorial there is a template with:
<p>
#{field 'tags'}
<label>Enter some tags:</label>
<input type="text" size="50"
name="${field.name}" value="${post?.tags?.join(' ')}" />
#{/field}
</p>
Check that you have it.

Property Editor not registered with the PropertyEditorManager error on Custom Validation Tag (java)

I am using TomCat 5.5 with MyFaces 1.1 and am trying to implement a custom regex validation tag.
My RegExValidator class looks like this:
public class RegExValidator implements Validator, StateHolder {
private String regex;
private boolean transientValue = false;
public RegExValidator() {
super();
}
public RegExValidator(String regex) {
this();
this.regex = regex;
}
public void validate(FacesContext context, UIComponent component, Object toValidate) throws ValidatorException {
if ((context == null) || (component == null)) {
throw new NullPointerException();
}
if (!(component instanceof UIInput)) {
return;
}
if (null == regex || null == toValidate) {
return;
}
String val = (String) toValidate;
if (!val.matches(regex)) {
FacesMessage errMsg = MessageFactory.createFacesMessage(context, Constants.FORMAT_INVALID_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, (new Object[]{regex}));
throw new ValidatorException(errMsg);
}
}
public Object saveState(FacesContext context) {
Object[] values = new Object[1];
values[0] = regex;
return (values);
}
public void restoreState(FacesContext context, Object state) {
Object[] values = (Object[]) state;
regex = (String) values[0];
}
public String getRegex() {
return regex;
}
public void setRegex(String regex) {
this.regex = regex;
}
public boolean isTransient() {
return transientValue;
}
public void setTransient(boolean transientValue) {
this.transientValue = transientValue;
}
}
My RegExValidatorTag class looks like this:
#SuppressWarnings("serial")
public class RegExValidatorTag extends ValidatorELTag {
private static String validatorID = null;
protected ValueExpression regex = null;
public RegExValidatorTag() {
super();
if (validatorID == null) {
validatorID = "RegExValidator";
}
}
public Validator createValidator() throws JspException {
FacesContext facesContext = FacesContext.getCurrentInstance();
RegExValidator result = null;
if (validatorID != null) {
result = (RegExValidator) facesContext.getApplication().createValidator(validatorID);
}
String patterns = null;
if (regex != null) {
if (!regex.isLiteralText()) {
patterns = (String) regex.getValue(facesContext.getELContext());
} else {
patterns = regex.getExpressionString();
}
}
result.setRegex(patterns);
return result;
}
public void setValidatorID(String validatorID) {
RegExValidatorTag.validatorID = validatorID;
}
/**
* #param regex
* the regex to set
*/
public void setRegex(ValueExpression regex) {
this.regex = regex;
}
}
My Taglibrary Descriptor looks like this:
<tag>
<name>regexValidator</name>
<tag-class>com.company.components.taglib.RegExValidatorTag</tag-class>
<attribute>
<name>regex</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
My face-common-config.xml has a Validator tag like this:
<validator>
<description>
Validate an input string value against a regular
expression specified by the "regex" attribute.
</description>
<validator-id>RegExValidator</validator-id>
<validator-class>com.company.components.validators.RegExValidator</validator-class>
<attribute>
<description>
The regular expression to test the value against
</description>
<attribute-name>regex</attribute-name>
<attribute-class>java.lang.String</attribute-class>
</attribute>
</validator>
And later on it is supposed to be used in a jsp file like this:
<tc:in value="${dataBean.currentBean.field}">
<a:regexValidator regex="${dataBean.currentBean.validationRegEx}" />
</tc:in>
When calling the page, the following error comes up:
javax.servlet.ServletException: javax.servlet.jsp.JspException: org.apache.jasper.JasperException: Unable to convert string "[\d{4}]" to class "javax.el.ValueExpression" for attribute "regex": Property Editor not registered with the PropertyEditorManager
Caused by:
org.apache.jasper.JasperException - Unable to convert string "[\d{4}]" to class "javax.el.ValueExpression" for attribute "regex": Property Editor not registered with the PropertyEditorManager
I hope I provided enough details for someone to help me out on this...
I seem to have a similar problem like yours, I'm trying to find the solution but seems that the problem is when using Tomcat or the application server(WebSphere Application Server 7.0) JSF libraries, my problem is that the new application server has new JSF libraries (1.2) instead of the 1.1 libraries that my old application server had. (Version 6.1)
To be more specific. my problem is described here. http://www-01.ibm.com/support/docview.wss?uid=swg21318801

Categories