Reputation: 923
I want to perform inline validation on the fields in a form, using JSR-303. By inline (aka on-the-fly) validation, I mean that each field is validated as the user works through the form (e.g. on blur or on key press), as opposed to deferring validation until a submit button is pressed. Typically, error messages are displayed near the input field.
I'm following the procedures described in GWT validation dev guide
where an example shows JSR-303 constraints being defined for the fields (in this case just one field, name
) in a Person
class:
// Copied from http://www.gwtproject.org/doc/latest/DevGuideValidation.html
public class Person implements Serializable {
@NotNull
@Size(min = 4, message = "Name must be at least 4 characters long.")
private String name;
}
The class(es) (just Person
in this case) to be validated are specified like this:
// Copied from http://www.gwtproject.org/doc/latest/DevGuideValidation.html
public final class MyValidatorFactory 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);
}
}
Suppose I have a TextBox
on which I want to perform inline validation.
I attempt to define constraints like this:
// Example of code that does not work!
import com.google.gwt.user.client.ui.TextBox;
import javax.validation.constraints.Pattern;
public class FooWidget extends TextBox {
@Pattern(regexp="^[0-9]+$", message="Foo: expected digits.")
public String getFoo() {
return getValue(); // from TextBox
}
}
with the corresponding definition in MyValidatorFactory
:
// Example of code that does not work!
@GwtValidation(FooWidget.class)
public interface GwtValidator extends Validator {
}
However, this does not compile (I'm using GWT 2.7.0), producing the following errors:
[ERROR] An internal compiler exception occurred
com.google.gwt.dev.jjs.InternalCompilerException: Unexpected error during visit.
at com.google.gwt.dev.jjs.ast.JVisitor.translateException(JVisitor.java:121)
at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:296)
at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:285)
at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:128)
at com.google.gwt.dev.jjs.ast.JCastOperation.traverse(JCastOperation.java:67)
at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:381)
at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:293)
at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:285)
at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:128)
at com.google.gwt.dev.jjs.ast.JDeclarationStatement.traverse(JDeclarationStatement.java:49)
at com.google.gwt.dev.jjs.ast.JModVisitor$ListContext.traverse(JModVisitor.java:95)
at com.google.gwt.dev.jjs.ast.JModVisitor.acceptWithInsertRemove(JModVisitor.java:351)
at com.google.gwt.dev.jjs.ast.JBlock.traverse(JBlock.java:92)
at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:381)
at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:293)
at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:149)
at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:145)
at com.google.gwt.dev.jjs.ast.JMethodBody.traverse(JMethodBody.java:83)
at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:381)
at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:293)
at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:285)
at com.google.gwt.dev.jjs.ast.JMethod.visitChildren(JMethod.java:600)
at com.google.gwt.dev.jjs.ast.JMethod.traverse(JMethod.java:569)
at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:381)
at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:293)
at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:285)
at com.google.gwt.dev.jjs.impl.UnifyAst.mainLoop(UnifyAst.java:1505)
at com.google.gwt.dev.jjs.impl.UnifyAst.exec(UnifyAst.java:870)
at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler$Precompiler.unifyJavaAst(JavaToJavaScriptCompiler.java:1305)
at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler$Precompiler.constructJavaAst(JavaToJavaScriptCompiler.java:1038)
at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler$Precompiler.precompile(JavaToJavaScriptCompiler.java:954)
at com.google.gwt.dev.jjs.MonolithicJavaToJavaScriptCompiler.precompile(MonolithicJavaToJavaScriptCompiler.java:303)
at com.google.gwt.dev.jjs.JavaScriptCompiler.precompile(JavaScriptCompiler.java:38)
at com.google.gwt.dev.Precompile.precompile(Precompile.java:286)
at com.google.gwt.dev.Precompile.precompile(Precompile.java:229)
at com.google.gwt.dev.Precompile.precompile(Precompile.java:145)
at com.google.gwt.dev.Compiler.run(Compiler.java:206)
at com.google.gwt.dev.codeserver.Recompiler.doCompile(Recompiler.java:333)
at com.google.gwt.dev.codeserver.Recompiler.compile(Recompiler.java:161)
at com.google.gwt.dev.codeserver.Recompiler.recompile(Recompiler.java:119)
at com.google.gwt.dev.codeserver.Outbox.recompile(Outbox.java:128)
at com.google.gwt.dev.codeserver.JobRunner.recompile(JobRunner.java:81)
at com.google.gwt.dev.codeserver.JobRunner.access$100(JobRunner.java:34)
at com.google.gwt.dev.codeserver.JobRunner$2.run(JobRunner.java:73)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoClassDefFoundError: Could not initialize class com.myco.myapp.FooWidget
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:260)
at com.google.gwt.validation.rebind.BeanHelperCache.createHelper(BeanHelperCache.java:85)
at com.google.gwt.validation.rebind.ValidatorGenerator.generateGwtSpecificValidator(ValidatorGenerator.java:131)
at com.google.gwt.validation.rebind.ValidatorGenerator.generate(ValidatorGenerator.java:67)
at com.google.gwt.core.ext.IncrementalGenerator.generateNonIncrementally(IncrementalGenerator.java:40)
at com.google.gwt.dev.javac.StandardGeneratorContext.runGeneratorIncrementally(StandardGeneratorContext.java:760)
at com.google.gwt.dev.cfg.RuleGenerateWith.realize(RuleGenerateWith.java:160)
at com.google.gwt.dev.shell.StandardRebindOracle$Rebinder.rebind(StandardRebindOracle.java:79)
at com.google.gwt.dev.shell.StandardRebindOracle.rebind(StandardRebindOracle.java:276)
at com.google.gwt.dev.shell.StandardRebindOracle.rebind(StandardRebindOracle.java:265)
at com.google.gwt.dev.DistillerRebindPermutationOracle.getAllPossibleRebindAnswers(DistillerRebindPermutationOracle.java:87)
at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.createStaticRebindExpression(UnifyAst.java:485)
at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.createRebindExpression(UnifyAst.java:443)
at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.handleMagicMethodCall(UnifyAst.java:576)
at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.endVisit(UnifyAst.java:306)
at com.google.gwt.dev.jjs.ast.JMethodCall.traverse(JMethodCall.java:248)
at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:381)
at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:293)
... 47 more
[ERROR] at _FooWidgetValidator.java(6): GWT.create(_FooWidgetValidator.class)
com.google.gwt.dev.jjs.ast.JMethodCall
[ERROR] at _FooWidgetValidator.java(6): (_FooWidgetValidator) GWT.create(_FooWidgetValidator.class)
com.google.gwt.dev.jjs.ast.JCastOperation
[ERROR] at _FooWidgetValidator.java(6): final static _FooWidgetValidator INSTANCE = (_FooWidgetValidator) GWT.create(_FooWidgetValidator.class)
com.google.gwt.dev.jjs.ast.JDeclarationStatement
[ERROR] at _FooWidgetValidator.java(5): {
final static _FooWidgetValidator INSTANCE = (_FooWidgetValidator) GWT.create(_FooWidgetValidator.class);
}
com.google.gwt.dev.jjs.ast.JBlock
[ERROR] at _FooWidgetValidator.java(5): {
final static _FooWidgetValidator INSTANCE = (_FooWidgetValidator) GWT.create(_FooWidgetValidator.class);
}
com.google.gwt.dev.jjs.ast.JMethodBody
[ERROR] at _FooWidgetValidator.java(5): private static final void $clinit();
com.google.gwt.dev.jjs.ast.JMethod
[ERROR] Compiler returned false
What's going on here and why doesn't this work?
The error messages refer to generated source code. I'd like to know how to relate them to my source code. Without understanding exactly what is broken, one resorts to experimental changes in search of a fix :-( .
One of those experimental changes has produced something that seems to work. I've posted another question about that: Inline validation using JSR-303 in GWT, part 2: A good implementation?, so if want to suggest how to do inline validation, maybe look at that question. This question is about understanding why the approach of putting constraints inside my FooWidget does not work.
One further detail: I know that the class to be validated should implement Serializable, as not to do so means it isn't a Java Bean. But there are plenty of examples on the web where that hasn't been done. Does it matter?
Upvotes: 0
Views: 174
Reputation: 64541
Caused by: java.lang.NoClassDefFoundError: Could not initialize class com.myco.myapp.FooWidget
You have to compile (javac
) your classes before calling the GWT Compiler (and put them in its classpath).
(note: the GWT validation generator should probably try to load the class from GWT's internal TypeOracle
rather than from the classloader; also note that GWT-Validation support is almost unmaintained – someone recently volunteered to maintain it, but hasn't contributed much yet)
Upvotes: 1