How to setConstraintViolations on EditorDriver using return value of client side Validator Validate method call
Asked Answered
M

2

5

Using GWT 2.5.0, I would like to use Client side validation and Editors. I encounter the following error when trying to pass the ConstraintViolation java.util.Set to the EditorDriver as follows.

Validator a = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<Person>> b = a.validate(person);
editorDriver.setConstraintViolations(b);

The method setConstraintViolations(Iterable<ConstraintViolation<?>>) in the type EditorDriver<Person> is not applicable for the arguments (Set<ConstraintViolation<Person>>)

The only somewhat relevant post I could find was Issue 6270!

Below is an Example which brings up a PopUpDialog with a Person Editor that allows you to specify a name and validate it against your annotations. Commenting out the personDriver.setConstraintViolations(violations); line in the PersonEditorDialog will allow you to run the example.

I don't have enough reputation points to post the image of the example.

Classes


Person

public class Person {

@NotNull(message = "You must have a name")

@Size(min = 3, message = "Your name must contain more than 3 characters")

private String name;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

PersonEditorDialog

public class PersonEditorDialog extends DialogBox implements Editor<Person> {

private static PersonEditorDialogUiBinder uiBinder = GWT
        .create(PersonEditorDialogUiBinder.class);

interface PersonEditorDialogUiBinder extends
        UiBinder<Widget, PersonEditorDialog> {
}

private Validator validator;

public PersonEditorDialog() {
    validator = Validation.buildDefaultValidatorFactory().getValidator();
    setWidget(uiBinder.createAndBindUi(this));
}

interface Driver extends SimpleBeanEditorDriver<Person, PersonEditorDialog> {
};

@UiField
ValueBoxEditorDecorator<String> nameEditor;

@UiField
Button validateBtn;

private Driver personDriver;

@UiHandler("validateBtn")
public void handleValidate(ClickEvent e) {
    Person created = personDriver.flush();
    Set<ConstraintViolation<Person>> violations = validator
            .validate(created);
    if (!violations.isEmpty() || personDriver.hasErrors()) {
        StringBuilder violationMsg = new StringBuilder();
        for (Iterator<ConstraintViolation<Person>> iterator = violations.iterator(); iterator.hasNext();) {
            ConstraintViolation<Person> constraintViolation = (ConstraintViolation<Person>) iterator
                    .next();
            violationMsg.append(constraintViolation.getMessage() + ",");
        }
        Window.alert("Detected violations:" + violationMsg);
         personDriver.setConstraintViolations(violations);
    }
}

@Override
public void center() {
    personDriver = GWT.create(Driver.class);
    personDriver.initialize(this);
    personDriver.edit(new Person());
    super.center();
}
}

SampleValidationFactory

public final class SampleValidationFactory extends AbstractGwtValidatorFactory {

/**
 * Validator marker for the Validation Sample project. Only the classes and
 * groups listed in the {@link GwtValidation} annotation can be validated.
 */
@GwtValidation(Person.class)
public interface GwtValidator extends Validator {
}

@Override
public AbstractGwtValidator createValidator() {
    return GWT.create(GwtValidator.class);
}
}

EditorValidationTest

public class EditorValidationTest implements EntryPoint {


/**
 * This is the entry point method.
 */
public void onModuleLoad() {
    PersonEditorDialog personEditorDialog = new PersonEditorDialog();
    personEditorDialog.center();
}
}

UiBinder

PersonEditorDialog.ui.xml

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:e="urn:import:com.google.gwt.editor.ui.client">
<ui:style>
    .important {
        font-weight: bold;
    }
</ui:style>
<g:HTMLPanel>
    <g:Label>Enter your Name:</g:Label>
    <e:ValueBoxEditorDecorator ui:field="nameEditor">
        <e:valuebox>
            <g:TextBox />
        </e:valuebox>
    </e:ValueBoxEditorDecorator>
    <g:Button ui:field="validateBtn">Validate</g:Button>
</g:HTMLPanel>
</ui:UiBinder> 

GWT Module

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.5.0//EN"
"http://google-web-toolkit.googlecode.com/svn/tags/2.5.0/distro-source/core/src/gwt-module.dtd">
<module rename-to='editorvalidationtest'>
<inherits name='com.google.gwt.user.User' />
<inherits name='com.google.gwt.user.theme.clean.Clean' />
<inherits name="com.google.gwt.editor.Editor"/>

<!-- Validation module inherits -->

<inherits name="org.hibernate.validator.HibernateValidator" />
<replace-with
    class="com.test.client.SampleValidationFactory">
    <when-type-is class="javax.validation.ValidatorFactory" />
</replace-with>

<!-- Specify the app entry point class. -->
<entry-point class='com.test.client.EditorValidationTest' />

<!-- Specify the paths for translatable code -->
<source path='client' />
<source path='shared' />

</module>

Libs required on Classpath

  • hibernate-validator-4.1.0.Final.jar
  • hibernate-validator-4.1.0.Final-sources.jar
  • validation-api-1.0.0.GA.jar (in GWT SDK)
  • validation-api-1.0.0.GA-sources.jar (in GWT SDK)
  • slf4j-api-1.6.1.jar
  • slf4j-log4j12-1.6.1.jar
  • log4j-1.2.16.jar
Mons answered 14/2, 2013 at 15:40 Comment(0)
M
7

As discussed in the comments, the following cast was determined to be a valid workaround.

Set<?> test = violations; 
editorDriver.setConstraintViolations((Set<ConstraintViolation<?>>) test);
Mons answered 19/2, 2013 at 14:36 Comment(1)
Lol, have I broken stack etiquette. I figured for clarity's sake it would be worth while to provide the answer as an answer. I appreciate the help @koma.Mons
D
3

This is what I do over and over again :

    List<ConstraintViolation<?>> adaptedViolations = new ArrayList<ConstraintViolation<?>>();
    for (ConstraintViolation<Person> violation : violations) {
        adaptedViolations.add(violation);
    }
    editorDriver.setConstraintViolations(adaptedViolations);

The driver has a wild card generic type defined and you can not pass in the typed constraint violations.

Dorado answered 14/2, 2013 at 17:23 Comment(5)
Can't you just cast it instead? Shouldn't that be able to make it behave rather than copying the list?Pertinacious
probably.. shorter and most likely more efficient, though for the resulting javascript, the compiler may be optimizing it;Dorado
The compiler will remove casts if you ask it to, see -XdisableCastChecking at developers.google.com/web-toolkit/doc/latest/… It cannot do the same for creating an array, copying contents, etc.Pertinacious
The only cast I've found to work is the following: Set<?> test = violations; editorDriver.setConstraintViolations((Set<ConstraintViolation<?>> test);Mons
@Mons that should do it and solve your issue. It is not elegant at all, but it works;Dorado

© 2022 - 2024 — McMap. All rights reserved.