Jak wiadomo wszystko w Java jest obiektem. Właśnie w ten sposób wszystkie informacje są zapisywane na serwerze. Natomiast informacje, które są wyświetlane w oknie przeglądarki muszą być prezentowane jako napisy, listy i obrazy. Powoduje to potrzebę konwersji tych dwóch rodzajów informacji. Na początku zajmiemy się tworzeniem własnych klas implementujących interfejs javax.faces.convert.Converter, który posiada dwie metody:
public Object getAsObject(FacesContext context, UIComponent component, String value) {...} public String getAsString(FacesContext context, UIComponent component, Object value) {...}
Pierwsza metoda naszej klasy konwertuje wpisaną wartość tekstową na obiekt dowolnej klasy gdy wysyłamy formularz na serwer, a druga metoda konwertuje wszystkie obiekty na postać łańcuchów i wysyła je do przeglądarki.
Utwórzmy następującą hierarchię klas:
public class ZipCode { //Klasa reprezentuje kod pocztowy. private String zip; public ZipCode(String zip) { this.zip = zip; } public String getZip() { return zip; } public void setZip(String zip) { this.zip = zip; } @Override public String toString() { return zip; } } //Klasa imię użytkownika. public class Name { private String name; Name(String value) { this.name = value; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return name; } } //Klasa reprezentuje obiektowe nazwisko. public class Surname { private String surname; public Surname(String surname) { this.surname = surname; } public String getSurname() { return surname; } public void setSurname(String surname) { this.surname = surname; } @Override public String toString() { return surname; } } //Nasz Bean, który trzyma dane formularza: public class RegistrationForm2 { private Name name = new Name(""); private Surname surname = new Surname(""); private ZipCode zipCode = new ZipCode(""); public Name getName() { return name; } public void setName(Name name) { this.name = name; } public Surname getSurname() { return surname; } public void setSurname(Surname surname) { this.surname = surname; } public ZipCode getZipCode() { return zipCode; } public void setZipCode(ZipCode zipCode) { this.zipCode = zipCode; } }Teraz aby implementacja JSF wiedziała co zrobić z naszymi obiektami ZipCode,Name,Surname musimy pomóc i stworzyć odpowiednie klasy konwerterów np: ZipCodeConverter, NameConverter i SurnameConverter. Gdy konwersja się nie powiedzie powinniśmy wystosować odpowiedni wyjątek ConverterException().
//--------------------------------- import java.util.Locale; import java.util.ResourceBundle; import javax.faces.application.FacesMessage; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.convert.Converter; import javax.faces.convert.ConverterException; /** * * @author riaa */ public class NameConverter implements Converter{ //Metoda konwertuje łańcuch z przeglądarki na obiekt typu Name. public Object getAsObject(FacesContext context, UIComponent component, String value) { //Jeżeli Name jest puste. if (value.isEmpty()) { //Pobieramy ustawienia lokalizacji użytkownika przeglądarki. Locale L = context.getViewRoot().getLocale(); //Tworzymy obiekt, który ładuje klasy przy pomocy metod klasy Class //a nie standardowo przez konstruktory. ClassLoader loader = Thread.currentThread().getContextClassLoader(); //Pobieramy obiekt mymessages.properties przy pomocy //statycznej metody: ResourceBundle.getBundle ResourceBundle bundle = ResourceBundle.getBundle(context.getApplication().getMessageBundle(), L, loader); //Wyszukujemy w pliku napisu o id = javax.faces.component.UIInput.REQUIRED. String resource = bundle.getString("javax.faces.component.UIInput.REQUIRED"); //Tworzymy obiekt wyświetlany w ice:message zastępując znak {0} // wartością id danej ice:inputText. FacesMessage f = new FacesMessage(FacesMessage.SEVERITY_ERROR, resource.replace("{0}", component.getId()), resource.replace("{0}", component.getId())); throw new ConverterException(f); } //Jeżeli Name zawiera tylko litery. if (value.matches("[A-Za-z]+")) return new Name(value); else { //Przypadek gdy ktoś w polu imię podał cyfrę. //Ten sam sposób na na początku. Locale L = context.getViewRoot().getLocale(); ClassLoader loader = Thread.currentThread().getContextClassLoader(); ResourceBundle bundle = ResourceBundle.getBundle(context.getApplication().getMessageBundle(), L, loader); String resource = bundle.getString("robpie.Name"); FacesMessage f = new FacesMessage(FacesMessage.SEVERITY_ERROR, resource.replace("{0}", component.getId()), resource.replace("{0}", component.getId())); throw new ConverterException(f); } } public String getAsString(FacesContext context, UIComponent component, Object value) { return value.toString(); } } //----------------------------------------- import java.util.Locale; import java.util.ResourceBundle; import javax.faces.application.FacesMessage; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.convert.Converter; import javax.faces.convert.ConverterException; /** * * @author riaa */ public class SurnameConverter implements Converter{ public Object getAsObject(FacesContext context, UIComponent component, String value) { if (value.isEmpty()) { Locale L = context.getViewRoot().getLocale(); ClassLoader loader = Thread.currentThread().getContextClassLoader(); ResourceBundle bundle = ResourceBundle.getBundle(context.getApplication().getMessageBundle(), L, loader); String resource = bundle.getString("javax.faces.component.UIInput.REQUIRED"); FacesMessage f = new FacesMessage(FacesMessage.SEVERITY_ERROR, resource.replace("{0}", component.getId()), resource.replace("{0}", component.getId())); throw new ConverterException(f); } if (value.matches("[A-Za-z]")) { return new Surname(value); } else { //Przypadek gdy ktoś w polu imię podał cyfrę. Locale L = context.getViewRoot().getLocale(); ClassLoader loader = Thread.currentThread().getContextClassLoader(); ResourceBundle bundle = ResourceBundle.getBundle(context.getApplication().getMessageBundle(), L, loader); String resource = bundle.getString("robpie.Surname"); FacesMessage f = new FacesMessage(FacesMessage.SEVERITY_ERROR, resource.replace("{0}", component.getId()), resource.replace("{0}", component.getId())); throw new ConverterException(f); } } public String getAsString(FacesContext context, UIComponent component, Object value) { return value.toString(); } } //--------------------------------- import java.util.Locale; import java.util.ResourceBundle; import javax.faces.application.FacesMessage; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.convert.Converter; import javax.faces.convert.ConverterException; /** * * @author riaa */ public class ZipCodeConverter implements Converter{ public Object getAsObject(FacesContext context, UIComponent component, String value) { if (value.matches("[0-9][0-9][-][0-9][0-9][0-9]")) return new ZipCode(value); else { Locale L = context.getViewRoot().getLocale(); ClassLoader loader = Thread.currentThread().getContextClassLoader(); ResourceBundle bundle = ResourceBundle.getBundle(context.getApplication().getMessageBundle(), L, loader); String resource = bundle.getString("robpie.ZipCode"); FacesMessage f = new FacesMessage(FacesMessage.SEVERITY_ERROR, resource, resource); throw new ConverterException(f); } } public String getAsString(FacesContext context, UIComponent component, Object value) { return value.toString(); } }Teraz do każdej kontrolki dodajmy znacznik f:converter.:
<h:form prependId="false"> <table> <tr> <td>Imię:</td> <td><ice:inputText id="name" value="#{registrationForm2.name}"> <f:converter converterId="NameConverter" /> <f:validateLength minimum="5" maximum="20" /> </ice:inputText></td> <td><ice:message for="name" /></td> </tr> <tr> <td>Nazwisko:</td> <td><ice:inputText id="surname" value="#{registrationForm2.surname}" > <f:validateLength minimum="5" maximum="20" /> </ice:inputText></td> <td><ice:message for="surname" /></td> </tr> <tr> <td>Kod pocztowy:</td> <td><ice:inputText id="zipCode" value="#{registrationForm2.zipCode}" required="true"> <f:converter converterId="ZipConverter" /> </ice:inputText></td> <td><ice:message for="zipCode" /></td> </tr> </table> <ice:commandButton value="Dalej" action="registration2"/> </h:form>
A na sam koniec musimy w pliku faces-config.xml dodać znacznik converter z odpowiednimi wpisami:
<converter> <converter-id>ZipConverter</converter-id> <converter-class>robpie.ZipCodeConverter</converter-class> </converter> <converter> <converter-id>NameConverter</converter-id> <converter-class>robpie.NameConverter</converter-class> </converter> <converter> <converter-for-class>robpie.Surname</converter-for-class> <converter-class>robpie.SurnameConverter</converter-class> </converter>
Teraz spróbujmy przetestować formularz:
0 comments:
Post a Comment