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.

Napsat komentář

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

 

 

Můžete použít tyto HTML tagy: <strong> <a href="" title="">
Chcete li do komentáře přidat zdrojový kód, obalte ho tagem [sourcecode language="jazyk"]


*