validation错误:值无效

我有一个ap:selectOneMenu的问题,无论我做什么我都无法让JSF调用JPA实体上的setter。 JSFvalidation失败并显示以下消息:

表单:位置:validation错误:值无效

我有这个工作在同一types的其他类(即连接表类),但不能为我的生活得到这个工作。

如果任何人都可以抛出一些疑难解答/debugging技巧这种问题,将不胜感激。

使用日志语句我已validation以下内容:

  1. Conveter正在返回正确的非null值。
  2. 我的JPA实体中没有Beanvalidation。
  3. setter setLocation(Location location)永远不会被调用。

这是我能做的最简单的例子,它根本行不通:

 <h:body> <h:form id="form"> <p:messages id="messages" autoUpdate="true" /> <p:selectOneMenu id="location" value="#{locationStockList.selected.location}" converter="locationConverter"> <p:ajax event="change" update=":form:lblLocation"/> <f:selectItems value="#{locationStockList.locationSelection}"/> </p:selectOneMenu> </h:form> </h:body> 

转换器:

 @FacesConverter(forClass=Location.class, value="locationConverter") public class LocationConverter implements Converter, Serializable { private static final Logger logger = Logger.getLogger(LocationConverter.class.getName()); @Override public Object getAsObject(FacesContext context, UIComponent component, String value) { if (value.isEmpty()) return null; try { Long id = Long.parseLong(value); Location location = ((LocationManagedBean) context.getApplication().getELResolver().getValue(context.getELContext(), null, "location")).find(id); logger.log(Level.SEVERE, "Converted {0} to {1}" , new Object[] {value, location}); return location; } catch (NumberFormatException e) { return new Location(); } } @Override public String getAsString(FacesContext context, UIComponent component, Object value) { if (value == null || value.toString().isEmpty() || !(value instanceof Location)) return ""; return String.valueOf(((Location) value).getId()); } } 

控制台输出:

 // Getter method INFO: Current value=ejb.locations.Location[id=null, name=null, latitude=0.0, longitude=0.0] // Session Bean INFO: Finding ejb.locations.Location with id=3 // Session Bean INFO: ### Returning : ejb.locations.Location[id=3, name=mdmd, latitude=4.5, longitude=2.3] // Converter SEVERE: Converted 3 to ejb.locations.Location[id=3, name=mdmd, latitude=4.5, longitude=2.3] // Getter method -> Where did my selected Location go ?? INFO: Current value=ejb.locations.Location[id=null, name=null, latitude=0.0, longitude=0.0] 

validation失败,并显示消息“form:location:Validation Error:Value is invalid”

这个错误归结为,在处理表单提交请求期间,所选项目与任何嵌套的<f:selectItem(s)>标记指定的任何可用select项目值不匹配。

作为防范被篡改/被黑客请求的一部分,JSF将重申所有可用的select项值,并testingselectedItem.equals(availableItem)是否至less返回一个可用项目值。 如果没有一个项目值匹配,那么你会得到完全这个validation错误。

这个过程基本如下,其中bean.getAvailableItems()虚构地表示由<f:selectItem(s)>定义的可用select项目的整个列表:

 String submittedValue = request.getParameter(component.getClientId()); Converter converter = component.getConverter(); Object selectedItem = (converter != null) ? converter.getAsObject(context, component, submittedValue) : submittedValue; boolean valid = false; for (Object availableItem : bean.getAvailableItems()) { if (selectedItem.equals(availableItem)) { valid = true; break; } } if (!valid) { throw new ValidatorException("Validation Error: Value is not valid"); } 

所以,基于上述逻辑,这个问题在逻辑上至less有以下原因:

  1. 所选项目在可用项目列表中缺失。
  2. 表示所选项目的类的equals()方法缺失或损坏。
  3. 如果涉及到自定义的Converter ,那么它在getAsObject()返回了错误的对象。 也许它甚至是null

要解决它:

  1. 确保在随后的请求中保留完全相同的列表,特别是在多个级联菜单的情况下。 在大多数情况下,使用bean @ViewScoped而不是@RequestScoped可以解决这个问题。 另外,请确保您不要在<f:selectItem(s)>的getter方法中执行业务逻辑,而是在@PostConstruct或一个操作事件(侦听器)方法中执行业务逻辑。 如果您依赖于特定的请求参数,那么您需要将它们明确地存储在@ViewScoped bean中,或者通过例如<f:param>在后续请求上重新传递它们。 另请参见如何select正确的bean作用域?
  2. 确保equals()方法正确执行。 这已经在标准Javatypes(如java.lang.Stringjava.lang.Number等)上完成,但不一定在自定义对象/ beans / entites上。 另请参见实施平等合同的正确方法 。 如果您已经在使用String ,请确保请求字符编码configuration正确。 如果它包含特殊字符,并且JSFconfiguration为将输出呈现为UTF-8,但将input解释为例如ISO-8859-1,则将失败。 另请参阅通过PrimeFacesinput组件检索的Unicodeinput已损坏 。
  3. debugging/logging您的自定义Converter的行为,并相应地修复它。 有关指导原则,另请参阅“转换器”的转换错误设置值如果您使用java.util.Date作为可用项目并使用<f:convertDateTime> ,请确保您不要忘记模式中的全部时间部分。 另请参见f:datetimeConverter中的“validation错误:值无效”错误 。

也可以看看:

  • 我们的selectOneMenu维基页面
  • 如何从数据库中填充h:selectOneMenu的选项?
  • 在JSF中创build多个依赖/级联selectOneMenu下拉列表

如果任何人都可以抛出一些疑难解答/debugging技巧这种问题,将不胜感激。

只要在这里提出一个清晰具体的问题。 不要问太广泛的问题;)

在我的情况下,我忘了执行正确的get / set方法。 这是因为我在开发过程中改变了很多属性。

没有一个合适的get方法,JSF就不能恢复你select的项目,并发生BalusC在他的回答的第1项中所说的:

1。 所选项目在可用项目列表中缺失。 如果可用项目的列表由请求范围的bean提供,而后者在后续请求中没有正确重新初始化,或者在getter方法中导致它以某种方式返回不同列表的方式执行业务作业,则可能发生这种情况。