在GWT中使用JSR-303进行内联验证,第1部分:TextBox上的验证失败。为什么?

时间:2014-11-25 15:55:35

标签: validation gwt gwt-compiler

我想使用JSR-303对表单中的字段执行内联验证。 通过内联(也称为动态)验证,我的意思是每个字段都在用户通过表单进行验证时进行验证(例如,在模糊或按键时​​), 而不是在按下提交按钮之前推迟验证。 通常,错误消息显示在输入字段附近。

我正在遵循GWT validation dev guide中描述的程序 其中一个示例显示了为name类中的字段(在本例中只是一个字段Person)定义的JSR-303约束:

// 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;
} 

要验证的类(在这种情况下只是Person)如下所示:

// 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);
  }
}

假设我有TextBox我想在其上执行内联验证。 我试图定义这样的约束:

// 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
  }
}

使用MyValidatorFactory中的相应定义:

// Example of code that does not work!
@GwtValidation(FooWidget.class)
public interface GwtValidator extends Validator {
}

但是,这不编译(我正在使用GWT 2.7.0),产生以下错误:

   [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

这里发生了什么,为什么这不起作用?

错误消息是指生成的源代码。 我想知道如何将它们与我的源代码联系起来。 如果不确切地知道什么是坏的,人们就会寻求修复的实验性变化:-(。

其中一项实验性改变产生了似乎有用的东西。 我发布了另一个问题: Inline validation using JSR-303 in GWT, part 2: A good implementation?,所以如果想建议如何进行内联验证,可以查看该问题。 这个问题是关于理解为什么在我的FooWidget中放置约束的方法不起作用。

进一步的细节:我知道要验证的类应该实现Serializable,因为不这样做意味着它不是Java Bean。但网上有很多例子尚未完成。这有关系吗?

1 个答案:

答案 0 :(得分:1)

Caused by: java.lang.NoClassDefFoundError: Could not initialize class com.myco.myapp.FooWidget

在调用GWT编译器之前必须编译(javac)类(并将它们放在类路径中)。

(注意:GWT验证生成器应该尝试从GWT的内部TypeOracle而不是从类加载器加载类;还要注意GWT-Validation支持几乎没有维护 - 有人最近自愿加入保持它,但还没有贡献很多)