- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在重构应用程序中的页面,并尝试对本身具有验证约束的对象执行递归验证。然而,发生了什么,我只收到一条错误,描述该对象无效。我想要的是嵌套对象的验证错误返回到页面。
ConsumerManagementController.java
@Controller
@SessionAttributes(ConsumerManagementController.CMD_NAME)
public class ConsumerManagementController {
private org.springframework.validation.Validator validator;
public ConsumerManagementController() {
validator = new net.sf.oval.integration.spring.SpringValidator.SpringValidator(new net.sf.oval.Validator());
}
@RequestMapping(value = FORM_VIEW, method = RequestMethod.POST)
protected ModelAndView processAdjustment(HttpServletRequest request,
Model model,
@ModelAttribute(CMD_NAME) ConsumerManagementCommand cmd,
BindingResult errors) throws Exception {
...
// Validating the ConsumerManagementCommand object
validator.validate(cmd, errors);
// RESULT
// org.springframework.validation.BeanPropertyBindingResult: 1 errors
// Field error in object 'cmc' on field 'consumerAdjustment': rejected value [[com.company.core.dto.ConsumerAdjustment - memo=, -- ]]; codes [net.sf.oval.constraint.AssertValid.cmc.consumerAdjustment,net.sf.oval.constraint.AssertValid.consumerAdjustment,net.sf.oval.constraint.AssertValid.com.company.core.dto.ConsumerAdjustment,net.sf.oval.constraint.AssertValid]; arguments []; default message [com.company.web.ops.commands.consumer.account.ConsumerManagementCommand.consumerAdjustment is invalid]
// Validating the ConsumerAdjustment object
ConsumerAdjustment consumerAdjustment = cmd.getConsumerAdjustment();
BeanPropertyBindingResult consumerAdjustmentErrors = new BeanPropertyBindingResult(consumerAdjustment, "consumerAdjustment");
validator.validate(consumerAdjustment, consumerAdjustmentErrors);
// RESULT
// org.springframework.validation.BeanPropertyBindingResult: 2 errors
// Field error in object 'consumerAdjustment' on field 'memo': rejected value []; codes [consumerAdjustment.memo.err.null.consumerAdjustment.memo,consumerAdjustment.memo.err.null.memo,consumerAdjustment.memo.err.null.java.lang.String,consumerAdjustment.memo.err.null]; arguments []; default message [com.company.core.dto.ConsumerAdjustment.memo cannot be empty]
...
}
}
ConsumerManagementCommand.java
@Guarded
public class ConsumerManagementCommand implements Serializable{
@AssertValid
private ConsumerAdjustment consumerAdjustment = new ConsumerAdjustment();
}
ConsumerAdjustment.java
public class ConsumerAdjustment extends AbstractDTO implements Serializable {
@NotNull(errorCode = ERR_MEMO_NULL)
@NotEmpty(errorCode = ERR_MEMO_NULL)
@Length(max = 500, errorCode = ERR_MEMO_LENGTH)
private String memo;
}
请参阅 RESULT 注释 ConsumerManagementController 以获取错误报告。
最佳答案
过一会儿再回到这个问题。我想出了如何实现我想要的。我不会讨论太多细节,但解决方案的根源相当复杂。
首先,我必须通过扩展 SpringValidator 创建自己的 validator :
class ConsumerManagementCommandSpringValidator extends SpringValidator{
Logger log = org.slf4j.LoggerFactory.getLogger(ConsumerManagementCommandSpringValidator.class);
public ConsumerManagementCommandSpringValidator(net.sf.oval.Validator validator) {
super(validator);
}
/**
* {@inheritDoc}
* Overridden method here to handle the nested validated objects of the {@link ConsumerManagementCommand}
* type. If a nested object fails validation, we need to identify the path to the field using
* the object name.
*/
@Override
public void validate(final Object objectToValidate, final Errors errors)
{
try
{
for (final ConstraintViolation violation : super.getValidator().validate(objectToValidate))
{
final OValContext ctx = violation.getContext();
final String errorCode = violation.getErrorCode();
final String errorMessage = violation.getMessage();
if (ctx instanceof FieldContext) {
Field field = ((FieldContext) ctx).getField();
String fieldName = field.getName();
try{
errors.rejectValue(fieldName, errorCode, errorMessage);
}catch(NotReadablePropertyException nrpe){
// Resolve the property location based on the object. Uses the class
// name of the field, tweaks the case and concatenates the value
StringBuilder objectReference = new StringBuilder(field.getDeclaringClass().getSimpleName());
fieldName = objectReference.substring(0, 1).toLowerCase().concat(objectReference.substring(1)).concat(".").concat(fieldName);
errors.rejectValue(fieldName, errorCode, errorMessage);
}
} else{
errors.reject(errorCode, errorMessage);
}
}
} catch (final ValidationFailedException ex) {
log.error("Unexpected error during validation", ex);
errors.reject(ex.getMessage());
}
}
}
其次,我创建了另一个扩展 net.sf.oval.Validator 的 validator :
class ConsumerManagementCommandValidator extends net.sf.oval.Validator{
@Override
protected void checkConstraintAssertValid(
List<ConstraintViolation> violations, AssertValidCheck check,
Object validatedObject, Object valueToValidate,
OValContext context, String[] profiles) throws OValException {
if (valueToValidate == null) return;
// ignore circular dependencies
if (isCurrentlyValidated(valueToValidate)) return;
// changed here access to private class variable to getter
final List<ConstraintViolation> additionalViolations = getCollectionFactory().createList();
validateInvariants(valueToValidate, additionalViolations, profiles);
if (additionalViolations.size() != 0) {
final String errorMessage = renderMessage(context, valueToValidate, check.getMessage(), check.getMessageVariables());
violations.add(new ConstraintViolation(check, errorMessage, validatedObject, valueToValidate, context, additionalViolations));
//add the violations to parent list :-)
violations.addAll(additionalViolations);
}
}
@Override
public List<ConstraintViolation> validate(Object validatedObject, String... profiles) throws IllegalArgumentException, ValidationFailedException {
// TODO Auto-generated method stub
return super.validate(validatedObject, profiles);
}
}
现在,我可以创建我的 validator 以供使用:
private ConsumerManagementCommandSpringValidator validator = new ConsumerManagementCommandSpringValidator(new ConsumerManagementCommandValidator());
我调用验证的地方:
// Validate the form
validator.validate(cmd, errors);
现在是命令对象。由于命令对象上有两个对象,因此我需要能够根据条件验证每个对象。使用 javascript EL 的 AssertValid:
// Custom assertion here, when the selected option is defined, only validate which is necessary
// We're using javascript expression language to do the comparison
@AssertValid(when="js:_this.selectedOption == com.company.core.adjustment.ConsumerManagementOption.ADJUST_CARD_VALUE")
private ConsumerAdjustment consumerAdjustment = new ConsumerAdjustment();
@AssertValid(when="js:_this.selectedOption == com.company.core.adjustment.ConsumerManagementOption.COMBINE_CARDS")
private ConsumerCombineAccounts consumerCombineAccounts = new ConsumerCombineAccounts();
现在,当我验证命令对象时,需要验证的嵌套对象将被处理,错误将上升到命令对象级别。
关于java - SpringValidator(net.sf.oval): Recursive Error Reporting,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31079827/
虽然我在理解递归方面没有任何问题,但我似乎无法理解汉诺塔问题的递归解决方案。这是来自 Wikipedia 的代码: procedure Hanoi(n: integer; source, dest,
虽然我在理解递归方面没有任何问题,但我似乎无法理解汉诺塔问题的递归解决方案。这是来自 Wikipedia 的代码: procedure Hanoi(n: integer; source, dest,
The Third Commandment的 The Little Schemer状态: When building a list, describe the first typical elemen
编辑 有关映射递归的“正确”Groovy 式方法,请参阅下面的@tim 解决方案。由于 Map findRecursive 在 Groovy 中尚不存在,如果您发现自己在应用程序的各个部分都需要此功能
这是尝试求解 3*3 的线性方程并打印结果,但在注释行中遇到了问题: 我在程序外部定义了 LinearSolution 模块,我应该在程序内部定义它吗?有什么区别? 为什么说该语句是递归的,你知道,当
我正在学习 Clojure 并从复制 Python 程序的功能开始,该程序将通过遵循(非常简单的)隐马尔可夫模型来创建基因组序列。 一开始,我坚持使用我已知的串行编程方式并大量使用 def 关键字,从
我有一个记录: type node = { content : string; parent : node option;
我发现 Java 8 已经显着清理了将文件内容读取到字符串中的过程: String contents = new String(Files.readAllBytes(Paths.get(new URI
我目前正在用 Java 编写一个图形库,我想要一个工具来可视化一些图形。我发现了 Graph-viz,它恰好是一种很好的(尽管有缺陷)做到这一点的方法。 在我的模型中,图由节点和边组成。每个节点都有一
昨天我遇到了这个pipes Common Lisp 库。它在某种程度上看起来很像 clojure 的惰性序列抽象,因此我决定使用它来实现 Common Lisp 中递归惰性斐波那契序列定义的经典(且优
昨天我遇到了这个pipes Common Lisp 库。它在某种程度上看起来很像 clojure 的惰性序列抽象,因此我决定使用它来实现 Common Lisp 中递归惰性斐波那契序列定义的经典(且优
我在开发一个递归函数时遇到了问题,该函数将查看两个列表是否彼此相等,包括查看子列表。到目前为止,我有: (defun are-equal2 (X Y) (cond ((null X) nil)
在 Abelson/Sussman 的经典著作《计算机程序的结构和解释》中,在关于树递归和斐波那契数列的第 1.2.2 节中,他们展示了这张图片: 计算第 5 个斐波那契数时生成的树递归过程 然后他们
SICP中的Section 1.2.1 中的作者在下面给出了这样的代码示例,以显示如何使用迭代过程解决阶乘问题: (define (factorial n) (fact-iter 1 1 n))
我继承了 的遗产Fortran 77 我现在的代码 试试 前往 编译 Fortran 2003 标准。我对 Fortran (我知道 C 和 Python)一无所知,我正在学习它。 下面的代码片段会导
这个警告来自哪里: Warning: `recursive` is deprecated, please use `recurse` instead 我在这里看到过:https://r-pkgs.or
Section 2.2 of the Happy user manual建议您使用左递归而不是右递归,因为右递归是“低效的”。基本上他们是说,如果您尝试解析一长串项目,右递归将溢出解析堆栈,而左递归使
问题 我有一个递归 CTE 查询,但是在创建循环时它失败了。我已经修复了简单的循环(例如 1 -> 2 -> 1),但无法修复更复杂的循环(例如 1 -> 2 -> 3 -> 2)。 查询详情 测试表
看完麻省理工学院的动态规划讲座后,我想练习一下斐波那契数列。我首先编写了朴素的递归实现,然后添加了内存。这是内存版本: package main import ( "fmt" ) func f
按照以下步骤,Cloudformation 堆栈可以进入递归锁: 在不导入值的情况下设置 CF(并创建堆栈) 使用相同的 CF 模板创建 soms 输出值(并更新堆栈) 在同一 CF 模板(和更新堆栈
我是一名优秀的程序员,十分优秀!