Primefaces Chips Web Component - SizeValidatorForCharSequence


#1

Hi!

I’ve asked Primefaces team and the Primefaces Core Developer oriented me: “Try to ask the hibernate validator guys. It seems like it uses getter and the property and those types doesn’t match”.

I have a CRUD and I want to change the inputTexArea:

<p:inputTextarea id=“tags” value="#{myController.selected.tags}" />

To the new Primefaces chips component:

<p:chips id=“tags” value="#{myController.selected.tags}" />

An entity class excerpt:

@Lob
@Size(max = 2147483647)
@Column(name = “tags”)
private String tags;
//GETTER AND SETTER OMITTED

The get method works fine, as the tags are displayed in the field as expected:

public List getTags() {
return Arrays.asList(tags.split(","));
}

The problem occurs when I try to Save in database, as an Exception occurs:

public void setTags(List tags) {
this.tags = String.join(",", tags);
}

//excerpt of the Exception:
java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.CharSequence at org.hibernate.validator.internal.constraintvalidators.SizeValidatorForCharSequence.isValid(SizeValidatorForCharSequence.java:33) at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateSingleConstraint(ConstraintTree.java:281)

Can you guys, please, help me?

Thanks in advance.


#2

Hi @Marcel,

So, indeed, it’s an Hibernate Validator issue. Basically you’re expected to follow the Java Bean rules so your getter should be consistent with your property.

So in the end, you would need a getTagList() method instead of getTags() to make it work.

Your case is interesting because we could probably decide that the getter is not relevant given its return type but I’m not sure we would want to go down this way.

For now, it would be better to just adapt your code.


#3

Hi @gsmet !

I’ve asked this question in the old Hibernate Forum, and @Sanne answered:

"the annotations are defined on the field so Validator is expecting to validate the Java type of the field, which is a String.

_Getters and setters should match the same type (so return a String and accept a String, not a a List): /beanvalidation.org/1.1/spec/#constraintdeclarationvalidationprocess-requirements

Even so, seems like Hibernate Validator should have used field access in your example.
Please share the version of Hibernate Validator you’re using, to see if we need to create a new bug in our issue tracker".

As the old Forum is read-only, I coul not inform the Hibernate version there, which is 4.3.

As you’ve oriented me, I’ve been trying to adapt my code, but I had no success.

The value of Primefaces chips component should be a List of strings (pg.103), so I mapped as below :

@Column(name = "TAGS")
private List<String> tags;

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

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

and got the Exception:

org.eclipse.persistence.exceptions.ConversionException
Exception Description: The object [exampleTag1, exampleTag2, exampleTag3], of class 
[class java.lang.String], from mapping 
[org.eclipse.persistence.mappings.DirectToFieldMapping[tags-->APP.PRODUCT.TAGS]] 
with descriptor [RelationalDescriptor(entity.Product --> 
[DatabaseTable(APP.PRODUCT)])], could not be converted to [class [B].

I’ve been stuck with this for a long time since I’ve asked it in other Forums (Primefaces Forum, Stackoverflow, Java CodeRanch, GUJ), but I had no success.

Please, can you help me to solve this ?


#4

You changed your ORM mapping and EclipseLink does not like it. Maybe adding an @ElementCollection annotation to the tags property would do it, I’m not familiar with EclipseLink.

To be honest, I was advocating a less intrusive change by just changing the name of your getTags() method to getTagList() without changing your mapping.


#5

Hi @gsmet.

Thanks for helping me !

That’s the solution I’ve got:

//entity bean column mapping :
@Lob
@Size(max = 2147483647)
@Column(name = "tagsColab")
private String tagsColab;

//entity bean methods:
public String getTagsColab() {
    return tagsColab;
}

public void setTagsColab(String tagsColab) {
    this.tagsColab = tagsColab;
}

public List<String> getTagsColabList() {
    if (tagsColab==null) {
        tagsColab = ""; // workaround to avoid NullPointerException when loading the form to insert new register
        }
    return Arrays.asList(tagsColab.split(","));
}

public void setTagsColabList(List<String> tagsColab) {
    this.tagsColab = (tagsColab); 
}

//JSF (use in the create or edit page):
<p:chips id="tagsColab" value="#{colabController.selected.tagsColabList}" />