-
1. Re: EntityHome validations
valatharv Feb 16, 2009 9:50 PM (in response to mcohnen)Are you trying to provide validation, if so this is simple sample, it checks for duplicate value.
Home
----
public String persist(){
try {
boolean boolDup = ValidationUtil.findDup(alKey);
if(boolDup){
return "duplicateValue";
}else{
.....
}
catch (Exception e) {
return "persistError";
}
super.persist();
}
xxxx.Page.xml
-------------
<navigation from-action="#{xxxxHome.persist}">
<rule if-outcome="duplicateValue">
<render view-id="/xxxxxEdit.xhtml">
<message severity="error">
Duplicate value found, please select different value.
</message>
</render>
</rule>
<rule if-outcome="persisted">
<end-conversation />
<redirect view-id="/xxxxxList.xhtml" />
</rule>
</navigation> -
2. Re: EntityHome validations
mcohnen Feb 17, 2009 10:29 AM (in response to mcohnen)Thank you for answer! Actually, my case is more complicated. I have a translation table, to apply i18n translations to jpa. This translations are not part of the Entity Object, but just a map in the EntityHome object. So, if there are errors in the validation of this fields, I should rollback all operations taken in the persist method. Is this possible? I'm returning
persistError
but this does not rollback all the operations done in the database (ie already added one of the translations).Is this approach possible?
Thank you!
-
3. Re: EntityHome validations
valatharv Feb 17, 2009 6:29 PM (in response to mcohnen)Trying to understand your issue, if Translation table is not part of entity, are the values inserted using jdbc or how ?
It will be nice if code block is posted.
-
4. Re: EntityHome validations
mcohnen Feb 17, 2009 6:46 PM (in response to mcohnen)Hi, I am using this library: http://code.google.com/p/jpa-translator
It basically adds some interceptors to the Entity. You configure the translation tables (using jpa) and then simply:
Translator translator = new Translator( Locale.GERMAN ); Hotel translatedHotel = translator.translate( hotel ); translatedHotel.getDescription(); // return description in german translatedHotel.setDescription( "die Beschreibung" ); // persist german description
Before saving this translated versions, I validate against the Hotel hibernate validations using ClassValidator. This is the code of my HomeEntity class:
public class TranslationEntityHome<E> extends EntityHome<E> { @In protected SeamTranslator translator; @In FacesMessages facesMessages; @In protected LocaleSelector localeSelector; @RequestParameter protected Boolean loadTranslations; private Map<String, Map<String, String>> translations; @Override @Begin public void create() { super.create(); translations = new HashMap<String, Map<String, String>>(); for (SelectItem locale:localeSelector.getSupportedLocales()){ if (!locale.getValue().toString().equals(LocaleConfig.instance().getDefaultLocale())){ translations.put(locale.getValue().toString(), new HashMap<String, String>()); } } } @Override public String update() { if (persistTranslations()==null){ return "persistError"; } return super.update(); } private String persistTranslations() { //getEntityManager().refresh(getInstance()); try { for (Map.Entry<String, Map<String, String>> entry : translations .entrySet()) { translator.setLocale(new Locale(entry.getKey())); E trans = translator.translate(getInstance()); for (Map.Entry<String, String> entry2 : entry.getValue() .entrySet()) { // Always allow blank messages if (entry2.getValue()==null || entry2.getValue().trim().length()==0){ continue; }else{ // Validation ClassValidator<E> validator = new ClassValidator<E>(getEntityClass()); InvalidValue[] errors = validator.getPotentialInvalidValues(entry2.getKey(), entry2.getValue()); for(InvalidValue iv:errors){ facesMessages.addToControl(iv); } if (errors.length>0){ return null; } } Class<?> c = getInstance().getClass(); Method m = c.getDeclaredMethod("set" + StringUtil.capitalize(entry2.getKey()), String.class); m.invoke(trans, entry2.getValue()); } } } catch (Exception e) { // TODO e.printStackTrace(); return null; }finally{ translator.resetLocale(); } return "persisted"; } @Override public String persist() { String res = super.persist(); if (persistTranslations()==null){ return null; } getEntityManager().flush(); return res; } @Override public E find() { E res = super.find(); if (loadTranslations!=null && loadTranslations) { try { for (Map.Entry<String, Map<String, String>> entry : translations .entrySet()) { translator.setLocale(new Locale(entry.getKey())); E trans = translator.translate(res); Class<?> c = res.getClass(); for (Field f : c.getDeclaredFields()) { if (f.isAnnotationPresent(Translate.class)) { String value = (String) c.getMethod( "get" + StringUtil.capitalize(f.getName())) .invoke(trans); translations.get(entry.getKey()).put(f.getName(), value); } } } } catch (Exception e) { // TODO e.printStackTrace(); }finally{ translator.resetLocale(); } }else{ translator.resetLocale(); res = translator.translate(res); } return res; } public Map<String, Map<String, String>> getTranslations() { return translations; } public void setTranslations(Map<String, Map<String, String>> translations) { this.translations = translations; } }
As you can see, I first save/validate the translations, that are hold in a map on the HomeEntity (just temporary), and then call super.persist() if everything goes fine. The problem is that I'm saving every translation (adding those interceptors) once it passes validation. Let's say validation is OK for translation in spanish (I call setMethod in the translated instance, but the second one fails. persistTranslations method will return null, so super.persist() won't be called, but the first interceptor (the one for the spanish translation) has already been set, and therefor commits. I want to rollback everything in the persist method if a validation error occurs...
I hope you can understand it now. If now, I will try to make it clearer.
Just want to rollback everything that happened in the persist method if some programatically circunstances (validation errors) occur.
Thank you very much!
-
5. Re: EntityHome validations
valatharv Feb 17, 2009 7:28 PM (in response to mcohnen)Your "programatically circumstances" will return null if any error, right?
I would say I am not an expert, so please don't mind if I am wrong. I can test it...
Why "getEntityManager().flush();" is called, I think super.persist() will take care of it.
a) You can try this, also you can try using "FlushModeType.MANUAL", I used it some time back in one of my entityHome.update
@Override
public String persist() {
if (persistTranslations()==null){
return null;
}else{
return super.persist();
}
}
b) @Begin(join=true, flushMode=org.jboss.seam.annotations.FlushModeType.MANUAL)
public String persist(){
//// SOME VALIDATIONS
return super.persist();
}