Tomáš Piňos
3.11.2010

Jak pořád nepsat labely



Formulářová pole, validační hlášky, hlavičky seznamů, historie změn entity, … je mnoho míst, kde je potřeba pracovat s popisy polí, která odpovídají vlastnostem nějaké třídy. Tento blog představí tip, jak si rutinní činnost zjednodušit.

Typická webová aplikace pracuje s množstvím formulářů, formulářových polí a jejich labelů, které se používají i při zobrazování výsledků validací, v hlavičkách seznamů nebo v různých detailech. Typické řešení Klíč k labelu ukazující na text z nějakého resource souboru je typicky použitý všude tam, kde je label třeba zobrazit. V šablonách stránek lze proto často najít podobný tag:

<f:textfield name=”payment.amount” label="label.payment.amount"/>

Vedle nutnosti psát label na mnoha místech se tím otevírá možnost pro nekonzistence v pojmenování polí, obtížné hledání správného klíče v resource souborech, duplikace v pojmenování a podobně. Anotace @Label Klíč labelu můžeme specifikovat přímo na entitě, se kterou pracujeme. Tou může být entita z doménového modelu nebo třeba třída reprezentující data z formuláře:

@Label(“label.payment”)
public class Payment {
  private BigDecimal amount;
  private CurrencyType currency;
  
  // gettery & settery... 
} 

Anotaci jde použít na úrovni třídy (celým klíčem je pak label třídy + jméno vlastnosti), fieldů nebo getter metod (tzn. jako předefinování přípony ke klíči třídy). Podobný přístup je možné použít i bez anotace, když zavedeme nějakou konvenci – klíčem k může být kvalifikované jméno třídy a “property path”. Tento přístup používá např. framework Grails. @Label anotace je oproti tomu více “nepřehlédnutelná” a úspornější, když používáme vnořené tříd. Oba přístupy jdou samozřejmě i kombinovat (“kde není anotace, tam je konvence”).

LabelResolver

Rozpoznávání labelu potom zajistí implementace rozhranní LabelResolver:

public interface LabelResolver {
  String resolveLabelKey(Class<?> beanClass, String propertyName); 
}

LabelResolver musí znát typ objektu, u kterého se zjišťuje label některé vlastnosti. Implementace je pak jednoduchá – prostá iterace přes “property path” a použití reflection API.

Použití
Použití si ukážeme na několika příkladech volání:
resolver.resolveLabelKey(Payment.class, “amount”);
resolver.resolveLabelKey(InstalmentPlan.class, “firstPayment.amount”);
resolver.resolveLabelKey(InstalmentPlan.class, “lastPayment.currency.code”); 

 Na formuláři pak stačí odkaz na jméno property, label už není třeba zadávat:

<f:textfield name=”payment.amount”/>

Abychom řešení mohli při tvorbě formulářů vůbec použít, je třeba mít pod kontrolou tagy (nebo jiný mechanismus), které v šablonách formulářů používáme. To je zároveň poměrně silná omezující podmínka – těžko “deklarativní” labely použít tam, kde se používá např. výhradně Struts2 a jeho tag library (nebo jiná knihovna hotových tagů). Použití nemusí být omezené jenom na webové aplikace, dobrý smysl může mít např. i při tvorbě Swing rozhranní. Námaha spojená s implementací tohoto přístupu stojí za to, pokud ho použijeme i jinde než jen u formulářových polí. Postup je výhodné integrovat např. s Bean Validation API pro tvorbu validačních hlášek. Při tomto přístupu jsou validace definované deklarativně na třídě nebo jejích vlastnostech a při sestavování chybové hlášky je proto nutné najít pro odkazované vlastnosti label. Další již zmíněné příklady jsou hlavičky seznamů nebo historie změn entity.

Závěr

Článek představil malé zjednodušení práce s labely, které se nám osvědčilo na několika webových projektech. Řešil malý a dopadem možná nevýznamný problém, ale i u malých a rutinních problémů je místo pro nápady. Považujete přístup s anotací @Label za zjednodušení nebo spíš komplikaci? Řešíte práci s labely jinak a netypicky? Používáte nějaký framework, který představuje jiné zajímavé řešení? Podělte se o své názory v diskuzi pod článkem.

Vaše emailová adresa nebude zveřejněna

Komentáře

Děkujeme za váš komentář
Další