Erreur de Validation: la valeur N'est pas valide
j'ai un problème avec un p:selectOneMenu, peu importe ce que je fais, Je ne peux pas obtenir JSF pour appeler le setter sur l'entité JPA. La validation JSF échoue avec ce message:
formulaire:emplacement: Erreur de Validation: la Valeur n'est pas valide
j'ai ce travail sur plusieurs autres classe du même type (c'est-à-dire, joindre des classes de table) mais ne peut pas pour la vie de moi obtenir ce travail.
si quelqu'un peut jeter dépannage/débogage des conseils pour ce genre de problème, il serait grandement apprécié.
J'ai vérifié ce qui suit à l'aide des relevés de journal:
- Le
Conveter
est de retour correct, nonnull
valeurs". - Je n'ai pas de validation dans mes entités JPA.
- le setter
setLocation(Location location)
n'est jamais appelé.
C'est l'exemple le plus simple que je puisse faire et cela ne marchera tout simplement pas:
<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>
convertisseur:
@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());
}
}
sortie Console:
// 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]
3 réponses
la Validation échoue avec le message "la forme:emplacement: Erreur de Validation: la Valeur n'est pas valide",
cette erreur se résume au fait que l'élément sélectionné ne correspond à aucune des valeurs disponibles de l'élément sélectionné spécifiées par une étiquette imbriquée <f:selectItem(s)>
pendant le traitement de la demande de soumission de formulaire.
dans le cadre de la protection contre les demandes trafiquées/piratées, JSF disponible sélectionnez les valeurs de l'élément et testez si selectedItem.equals(availableItem)
renvoie true
pour au moins une valeur de l'élément disponible. Si aucune valeur d'article ne correspond, alors vous obtiendrez exactement cette erreur de validation.
ce processus est sous les couvertures essentiellement comme ci-dessous, où bean.getAvailableItems()
représente fictionnellement la liste complète des éléments disponibles sélectionner comme défini par <f:selectItem(s)>
:
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");
}
Donc, basé sur la logique ci-dessus, ce problème peut logiquement avoir au moins les causes suivantes:
- L'élément sélectionné est manquant dans la liste des éléments disponibles.
- la méthode
equals()
de la classe représentant l'élément sélectionné est manquante ou cassée. - si une coutume
Converter
est impliquée, alors elle a retourné le mauvais objet dansgetAsObject()
. Peut-être mêmenull
.
pour le résoudre:
- veiller à ce que la même liste soit conservée lors de la requête suivante, en particulier dans le cas de plusieurs menus en cascade. Faire le haricot
@ViewScoped
au lieu de@RequestScoped
devrait le corriger dans la plupart des cas. Assurez-vous également que vous n'effectuez pas la logique d'affaires dans la méthode getter de<f:selectItem(s)>
, mais plutôt dans@PostConstruct
ou une méthode d'action event (listener). Si vous comptez sur des paramètres de requête spécifiques, alors vous devez les stocker explicitement dans le@ViewScoped
, ou de les transmettre à nouveau sur des demandes ultérieures par exemple<f:param>
. Voir aussi comment choisir le bon Bean scope? - S'assurer que la méthode
equals()
est appliquée correctement. Cela est déjà fait correctement sur les types Java standard tels quejava.lang.String
,java.lang.Number
, etc, mais pas nécessairement sur les objets/fèves/entités personnalisés. Voir aussi bonne façon de mettre en œuvre équivaut à un contrat . Dans le cas où vous êtes déjà en utilisantString
, assurez-vous que le codage de caractères de la requête est configuré correctement. S'il contient des caractères spéciaux et que JSF est configuré pour rendre la sortie UTF-8 mais interprète l'entrée comme par exemple ISO-8859-1, alors il échouera. Voir aussi a. O. Unicode input retrieved via PrimeFaces components input become corrupted . - déboguer / enregistrer les actions de votre coutume
Converter
et le corriger en conséquence. Pour les directives, voir aussi Valeur de paramètre D'erreur de Conversion pour 'convertisseur null ' dans le cas où vous utilisezjava.util.Date
comme articles disponibles avec<f:convertDateTime>
, assurez-vous que vous n'oubliez pas la partie temps plein dans le modèle. Voir aussi "erreur de Validation: la valeur n'est pas valide" erreur de f:datetimeConverter .
voir aussi:
- notre
selectOneMenu
page wiki - Comment remplir les options de H:selectOneMenu à partir de la base de données?
- Faire dépendantes multiples / en cascade selectOneMenu listes déroulantes dans JSF
si n'importe qui peut jeter quelques conseils de dépannage/débogage pour ce genre de problème, il serait grandement apprécié.
il suffit de demander un question claire et concrète. Ne posez pas trop de questions générales ;)
dans mon cas, j'ai oublié d'implémenter une méthode get/set correcte. Cela s'est produit parce que j'ai changé beaucoup d'attributs tout au long du développement.
sans une méthode get appropriée, JSF ne peut pas récupérer votre article sélectionné, et se passe ce que BalusC a dit au point 1 de sa réponse:
1 . L'élément sélectionné est manquant dans la liste des éléments disponibles. Cela peut se produire si la liste des articles disponibles est servie par une demande scoped bean qui n'est pas correctement réinitialisé sur demande ultérieure, ou fait incorrectement le travail d'affaires à l'intérieur d'une méthode getter qui lui fait retourner une liste différente d'une certaine manière.
il peut s'agir d'un problème de Convertisseur ou d'un problème DTO. Essayez de résoudre ceci, en ajoutant les méthodes hashCode() et equals() dans votre DTO objet; dans le scénario ci-dessus vous pouvez générer ces méthodes dans la classe d'objet Location qui indique comme 'DTO' ici.
exemple:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Location other = (Location) obj;
if (id != other.id)
return false;
return true;
}
- veuillez noter que l'exemple ci-dessus est pour un " id "de type "long".