Pemrograman Web Lanjut
© 2016 Niko Ibrahim, MIT
Fakultas Teknologi Informasi
Universitas Kristen Maranatha
Tujuan
Mahasiswa memahami bagaimana data yang
dikirimkan melalui form dapat di
konversi
ke
dalam objek Java
Mahasiswa memahami bagaimana proses
konversi data terjadi
Mahasiswa memahami bagaimana proses
validasi
data terjadi
Mahasiswa memahami cara menampilkan
Lecture’s Outline
Proses Konversi dan Validasi
Penggunaan Standard Converters
Penggunaan Standard Validators
Custom Converters and Validators
Latihan dan Tutorial
Proses Validasi dan Konversi Data
Aplikasi web dapat menyimpan berbagai jenis tipe data. Namun,
komponen input pada form hanya bisa menerima data dengan tipe String.
Berikut penjelasan proses di atas:
◦ User meng-input data pada form sebagai sebuah “STRING”
◦ Pada saat browser mengirimkan inputan tsb ke server, nilai yang di-submit akan dikonversi ke dalam “local value” (berupa tanggal, int, float, dll), dan kemudian divalidasi berdasarkan kondisi tertentu.
◦ Jika proses konversi/validasi berjalan lancar, maka “local value” tsb akan disimpan di dalam property managed bean.
ID dari JSF
Standard Converters
Berikut ini adalah Standard Conveters yang ada di JSF:
BigDecimalConverter konversi String ke java.math.BigDecimal BigIntegerConverter konversi String ke java.math.BigInteger BooleanConverter konversi String ke java.lang.Boolean
ByteConverter konversi String ke type java.lang.Byte
CharacterConverter konversi String ke java.lang.Character
DateTimeConverter konversi String ke java.util.Date dengan format default DoubleConverter konversi String ke java.lang.Double
EnumConverter konversi String ke type java.lang.Enum FloatConverter konversi String ke java.lang.Float
IntegerConverter konversi String ke java.lang.Integer LongConverter konversi String ke java.lang.Long
NumberConverter konversi String ke java.lang.Number ShortConverter konversi String ke java.lang.Short
Penggunaan Atribut
Converter
Ada 3 cara untuk meng-attach converter pada suatu
komponen;
a)
Menambahkan atribut “converter” pada tag komponen
dan menyebutkan ID converter yang diinginkan
<h:outputText value="#{payment.date}"
converter
="
javax.faces.DateTime
"/>
b)
Tanpa menggunakan attributes:
<h:outputText value="#{payment.date}"> <f:convertDateTime/>
</h:outputText>
c)
Atau menggunakan cara berikut:
<h:outputText value="#{payment.date}">
<f:converter converterId="javax.faces.DateTime"/> </h:outputText>
Atribut
Number Converters
Atribut Keterangan
currencyCode The ISO 4217 currency code, applied only when formatting currencies. A three-letter codes such as “USD” for the United States Dollar, “GBP” for the United Kingdom Pound, and “EUR” for the Euro. I found that not all codes listed in ISO 4217 were implemented.
currencySymbol Currency symbol, is applied only when formatting currencies. If the
currency code is set then currencySymbol will be ignored. This is the literal currency symbol, such as “$”.
groupingUsed Flag specifying whether formatted output will contain grouping separators. Default value is true.
integerOnly Flag specifying whether only the integer part of the value will be formatted and parsed. Default value is false.
maxFractionDigits Maximum number of digits that will be formatted in the fractional portion of the output.
maxIntegerDigits Maximum number of digits that will be formatted in the integer portion of the output.
minFractionDigits Minimum number of digits that will be formatted in the fractional portion of the output.
Atribut Number Converters (cont.)
Atribut Keterangan
minIntegerDigits Minimum number of digits that will be formatted in the integer portion of the output.
locale A java.util.Locale used to define a language and country. If not specified, the Locale returned by FacesContext.getViewRoot().getLocale() will be used.
pattern Custom formatting pattern which determines how the number string should be formatted and parsed.
Examples:
###,### 123,456
$###,###.## $123,456.99 #.### 1.789
type Specifies the number type. Valid values are “number”, “currency”, and “percent”. Default value is “number”.
Contoh Number Converter
untuk
OutputText
Pada contoh ini, kita gunakan atribut “locale”
Contoh Number Converter untuk
InputText
Managed Bean:
private int salary, discount;
private double population;
Atribut
DateTime
Converters
Atribut Keterangan & Contoh
dateStyle default Jan 1, 2006 1:20:45 PM short 1/1/06 1:20:45 PM
medium Jan 1, 2006 1:20:45 PM long January 1, 2006 1:20:45 PM
full Sunday, January 1, 2006 1:20:45 PM locale java.util.Locale(String language, String country)
Locale.SPAIN, Locale.CANADA, etc. pattern Java.text.SimpleDateFormat
yyyy.MM.dd ‘at’ HH:mm:ss z 2007.01.01 at 12:05:30 PDT EEE, MMM d ‘yy Mon, Jan 1, ‘07
h:mm a 10:05 AM
hh ‘o’ ‘clock’ a, zzzz 12 o’ clock PM, Pacific Daylight Time timeStyle default Jan 1, 2007 10:05:30 AM
short 1/1/07 10:05:30 AM
medium Jan 1, 2006 10:05:30 AM long January 1, 2007 10:05:30 AM
full Monday, January 1, 2006 10:05:30 AM timeZone java.util.TimeZone
type Both Date and time. date Date only.
Contoh
convertDateTime
untuk
InputText
User harus meng-input dalam format “MM/dd/yyyy”,
kalau tidak maka akan muncul pesan eror.
JSF akan secara otomatis melakukan konversi input
Pesan Error Pada Converter
Pada saat terjadi eror pada conversi, maka
akan terjadi dua hal berikut:
1.
Komponen yang mengalami conversion
error akan
mengirimkan pesan
dan
mendeklarasikan dirinya sebagai invalid.
2.
JSF akan
menampilkan ulang
halaman
tersebut setelah proses validasi selesai.
Halaman ini akan menampilkan semua nilai
yang diinput oleh user (tidak ada inputan
yang hilang)
Cara Menampilkan Pesan Error
Pesan eror sangat berguna agar user dapat melihat
penyebab eror pada proses konversi dan validasi.
Kita dapat menggunakan tag
h:message
Contoh:
<h:inputText id="amount" label=“Amount" value="#{payment.amount}"/>
Menampilkan
SEMUA
pesan Error
Tag
h:message
hanya menghasilkan satu pesan.
Kita dapat menampilkan semua pesan (summary) yang
dihasilkan oleh semua komponen dengan menggunakan
tag
h:messages
.
Tips: Untuk h:messages, biasanya kita gunakan atribut
“table” agar pesan berbaris secara vertikal.
Menggunakan Custom Error Message
Tag: converterMessage
Contoh:
DO IT YOURSELF PROJECT
Latihan Menggunakan Standard Converters
Untuk mengetahui lebih dalam mengenai
penggunaan standart/build-in converter,
buatlah sebuah aplikasi Web
yang berfungsi
untuk memproses pembayaran
e-commerce.
Data pembayaran memiliki:
◦
Jumlah yang harus dibayar (tipe double)
◦
Nomor kartu kredit (tipe String)
Latihan 01: Converter
Create, deploy, and run “Converter” project
Note: berikan pula “custom error message”
2. Using Standard Validators
Fungsi utama dari Validator adalah untuk melindungi data
model dari ketidakkonsistenan yang dapat disebabkan
apabila inputan tidak dapat divalidasi.
JavaServer Faces memiliki mekanisme built-in untuk
melakukan validasi seperti:
◦ Memeriksa panjang sebuah string
◦ Memeriksa batasan dari suatu angka (misal > 0 atau > 100)
Standard Validator
Atribut Keterangan & Contoh
LengthValidator Checks whether the length of a component’s value is within a certain range. This validator counts the number of characters.
Minimum – The minimum acceptable number of characters. Maximum – The maximum acceptable number of characters.
LongRangeValidator Checks whether the value of a component is within a certain range. The validator will attempt to convert the number to a Java long primitive. If minimum and
maximum attributes are used the validator will ensure that the value entered is within the minimum and maximum range. If the minimum and maximum attribute are omitted then the validator ensures that the value is numeric.
Minimum – The minimum acceptable numeric value. Maximum – The maximum acceptable numeric value.
DoubleRangeValidator Checks whether the value of a component is within a certain range. The value must be numeric or convertible to a numeric value. The
validator will attempt to convert the number into a Java double primitive. If
minimum and maximum attributes are used the validator will ensure that the value entered is within the minimum and maximum range. If the minimum and maximum attribute are omitted then the validator only ensures that the value is numeric. Minimum – The minimum acceptable numeric value.
Maximum – The maximum acceptable numeric value.
required If a UIInput component does not have the required attribute set to “true” and the user does not enter a value, then the validator will not be called. Remember to set required=”true”, if you want to force validation.
Length Validator
Contoh validasi panjang inputan:
<h:inputText id="card" value="#{payment.card}">
<
f:validateLength
minimum="13"/>
Range validator
Digunakan untuk mem-validasi inputan berupa angka
Contoh validator berikut memeriksa apakah suatu angka
inputan antara 10 dan 1000:
<h:inputText id="amount" value="#{payment.amount}">
<f:validateLongRange minimum="10" maximum="10000"/> </h:inputText>
Checking for
Required
Values
Untuk memeriksa apakah suatu nilai diisi atau tidak, kita
gunakan atribut
required="true"
:
Contoh:
<h:inputText id="date" value="#{payment.date}" required="true"/>
Semua tag input JSF dapat memiliki atribut required.
Kita juga bisa menggabungkan penggunaan atribut required
dengan validator lain:
Contoh:
<h:inputText id="card" value="#{payment.card}" required="true"> <f:validateLength minimum="13"/>
An alternate syntax
Kita dapat menggunakan sintaks alternatif dalam
menggunakan validator, yaitu menggunakan tag <
f:validator
>.
Kita sebutkan saja ID dari validator beserta parameternya.
Contoh:
<h:inputText id="card" value="#{payment.card}">
<f:validator validatorId="javax.faces.validator.LengthValidator"> <f:attribute name="minimum" value="13"/>
</f:validator> </h:inputText>
Displaying Validation Errors
Pesan error pada proses validasi sama
seperti pada proses konversi.
Tag:
◦
h:message atau
A Custom Message
Sama seperti pada proses konversi, kita juga dapat
memberikan “custom message” pada validasi.
Contoh:
<h:inputText id="card" value="#{payment.card}" required="true">
requiredMessage="#{msgs.cardRequired}"
validatorMessage="#{msgs.cardInvalid}"> <f:validateLength minimum="13"/>
Bypassing Validation
Kita dapat mengabaikan proses validasi.
Misalnya, apabila kita ingin meletakkan tombol
“Cancel” atau “Reset” pada sebuah form,
maka kita harus melakukan pengabaian pada
proses validasi dengan menggunakan atribut
“
immediate
”
Contoh:
<h:commandButton value="Cancel" action="cancel"
immediate="true"/>
Latihan 02: Validator
Modifikasi project sebelumnya dan berikan validator
required pada semua inputan, amount > 1000, dan panjang
kartu kredit > 13 dan < 16.
3. Programming with Custom Converters
Pada aplikasi yang kompleks, seperti aplikasi e-commerce, kita
seringkali membutuhkan converter dan validator di luar standar
yang disediakan oleh JSF.
Misalnya, kita perlu melakukan konversi tipe data selain
“number” dan “date”, juga perlu melakukan validasi yang spesifik
misalnya memeriksa suatu inputan kartu kredit.
Pada dasarnya, sebuah converter merupakan suatu class yang
mengkonversi strings dan objects. Sebuah converter harus
selalu meng-implement interface Converter, yang memiliki dua
buah method berikut:
◦ Object getAsObject(FacesContext context, UIComponent component, String newValue) berfungsi mengubah String menjadi object,
method ini dipanggil ketika user memasukkan sebuah String, misalnya di dalam input textfield. (PROSES KONVERSI)
◦ String getAsString(FacesContext context, UIComponent component, Object value) berfungsi mengubah object menjadi String untuk ditampilkan di user interface. (PROSES FORMATTING)
Contoh Custom Converter:
CreditCardConverter.java Untuk mengilustrasikan custom converter, kita akan membuat sebuah
class bernama “CreditCardConverter”, yang memungkinkan kita untuk menginput nomor kartu kredit dengan atau tanpa spasi.
Contoh input kartu kredit yang diperbolehkan:
◦ 1234567890123456 (tanpa spasi)
◦ 1234 5678 9012 3456 (dengan spasi)
Pada class ini, perhatikan 2 method berikut:
◦ getAsObject: menghapus semua karakter spasi, memeriksa apakah ada karakter yang bukan digit, dan membuat object CreditCard
◦ getAsString: melakukan formatting nomor kartu kredit sesuai yang
diinginkan user, digit-digit kartu kredit dipolakan sesuai dengan tipe-nya, sbb:
Tipe kartu Digit Format
MasterCard 16 5xxx xxxx xxxx xxxx Visa 16 4xxx xxxx xxxx xxxx Visa 13 4xxx xxx xxx xxx Discover 16 6xxx xxxx xxxx xxxx American Express 15 37xx xxxxxx xxxxx American Express 22 3xxxxx xxxxxxxx xxxxxxxx Diners Club, Carte Blanche 14 3xxxx xxxx xxxxx
CreditCardConverter.java
package mypkg; 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;public class CreditCardConverter implements Converter {
public Object getAsObject(FacesContext context, UIComponent component, String newValue) throws ConverterException {
StringBuilder builder = new StringBuilder(newValue); boolean foundInvalidCharacter = false;
char invalidCharacter = '\0'; int i = 0;
while (i < builder.length() && !foundInvalidCharacter) { char ch = builder.charAt(i); if (Character.isDigit(ch)) i++; else if (Character.isWhitespace(ch)) builder.deleteCharAt(i); else { foundInvalidCharacter = true; invalidCharacter = ch; } } if (foundInvalidCharacter) {
FacesMessage message = mypkg.util.Messages.getMessage( "mypkg.messages", "badCreditCardCharacter",
new Object[]{ new Character(invalidCharacter) }); message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ConverterException(message); }
return new CreditCard(builder.toString()); } // end of getAsObject
CreditCardConverter.java (cont.)
public String getAsString(FacesContext context, UIComponent component, Object value) throws ConverterException {
// length 13: xxxx xxx xxx xxx // length 14: xxxxx xxxx xxxxx // length 15: xxxx xxxxxx xxxxx // length 16: xxxx xxxx xxxx xxxx // length 22: xxxxxx xxxxxxxx xxxxxxxx String v = value.toString(); int[] boundaries = null; int length = v.length(); if (length == 13)
boundaries = new int[]{ 4, 7, 10 }; else if (length == 14)
boundaries = new int[]{ 5, 9 }; else if (length == 15)
boundaries = new int[]{ 4, 10 }; else if (length == 16)
boundaries = new int[]{ 4, 8, 12 }; else if (length == 22)
boundaries = new int[]{ 6, 14 }; else
return v;
StringBuilder result = new StringBuilder(); int start = 0;
for (int i = 0; i < boundaries.length; i++) { int end = boundaries[i];
result.append(v.substring(start, end)); result.append(" "); start = end; } result.append(v.substring(start)); return result.toString(); } // end of getAsString } // end of class
CreditCard.java
package mypkg;
public class CreditCard { private String number;
public CreditCard(String number) { this.number = number; } public String toString() { return number; }
Using & Configuring Custom Validator
(Menggunakan XML)
Agar custom converter bisa digunakan, maka kita harus
mendefinisikannya di dalam faces-config.xml sbb:
<converter>
<converter-id>mypkg.CreditCard</converter-id>
<converter-class>mypkg.CreditCardConverter</converter-class> </converter>
Sekarang kita bisa menggunakan tag f:converter dan menentukan id
dari custom converter yang sudah kita buat:
<h:inputText value="#{payment.card}">
<f:converter converterId=“mypkg.CreditCard"/> </h:inputText>
Atau menggunakan converter attribute:
Using & Configuring Custom Validator
(Menggunakan Annotation)
Kita dapat menggunakan annotation
@FacesConverter
pada class Custom Converter yg sudah kita buat sbb:
@FacesConverter(“mypkg.CreditCard")
Latihan 03: Converter02
Bukalah project
Custom-Converter-dan-Validator-Original
Perhatikan class custom converter yang telah disediakan:
“
CreditCardConverter.java
” dan juga converter bean
“
CreditCard.java
”
Perhatikan managed bean “
PaymentBean.java
” yang sudah
mengandung property CreditCard
Pelajari cara penggunaan
messages
di aplikasi ini
Tugas Anda:
1. Berikan atribut value (payment.card) dan tag <f:converter> pada inputText kartu kredit di index.xhtml
2. Berikan tag <f:converter> pada outputText kartu kredit di result.xhtml
3. Berikan annotation pada CreditCardConverter, atau bisa juga mendefinisikan di dalam faces-config.xml
Latihan 03: Converter2 (screenshots)
4. Programming with Custom Validators
Selain custom converter, aplikasi yang kompleks juga
seringkali membutuhkan custom validator di luar standar
yang disediakan oleh JSF.
Untuk mengimplementasikan customer validator class, kita
membutuhkan dua proses yang sama seperti di custom
converter:
1. Buat sebuah validator class yang mengimplementasi Validator interface:
javax.faces.validator.Validator interface
2. Definisikan validator class tersebut di dalam file configuration(faces-config.xml)
Validator interface hanya memiliki sebuah method:
◦ void validate: memvalidasi komponen yang mengandung class calidator ini.
Contoh kasus custom validator
Pada input kartu kredit, kita perlu melakukan validasi
nomor yang diinputkan.
Salah satu algoritma yang sering digunakan sebagai
validasi kartu kredit adalah Luhn Check.
Penjelasan lengkap mengenai Luhn Check:
http://www.merriampark.com/anatomycc.htm
Contoh kartu kredit yang benar berdasarkan Luhn
Luhn Check Algorithm
private static boolean luhnCheck(String cardNumber) { int sum = 0;
for(int i = cardNumber.length() - 1; i >= 0; i -= 2) {
sum += Integer.parseInt(cardNumber.substring(i, i + 1)); if(i > 0) {
int d = 2 * Integer.parseInt(cardNumber.substring(i - 1, i)); if(d > 9) d -= 9; sum += d; } } return sum % 10 == 0; }
CreditCardValidator.java
package mypkg; import javax.faces.application.FacesMessage; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.validator.Validator; import javax.faces.validator.ValidatorException;public class CreditCardValidator implements Validator {
public void validate(FacesContext context, UIComponent component, Object value) {
if(value == null) return; String cardNumber;
if (value instanceof CreditCard) cardNumber = value.toString(); else cardNumber = getDigitsOnly(value.toString()); if(!luhnCheck(cardNumber)) { FacesMessage message = mypkg.util.Messages.getMessage(
"mypkg.messages", "badLuhnCheck", null); message.setSeverity(FacesMessage.SEVERITY_ERROR); throw new ValidatorException(message);
} }
CreditCardValidator.java (cont.)
private static boolean luhnCheck(String cardNumber) {int sum = 0;
for(int i = cardNumber.length() - 1; i >= 0; i -= 2) {
sum += Integer.parseInt(cardNumber.substring(i, i + 1)); if(i > 0) {
int d = 2 * Integer.parseInt(cardNumber.substring(i - 1, i)); if(d > 9) d -= 9; sum += d; } } return sum % 10 == 0; }
private static String getDigitsOnly(String s) { StringBuilder digitsOnly = new StringBuilder (); char c;
for(int i = 0; i < s.length (); i++) { c = s.charAt (i); if (Character.isDigit(c)) { digitsOnly.append(c); } } return digitsOnly.toString (); }
Using and Configuring Custom Validator
(using faces-config.xml)
Now that we have created a validator, we need to register it in a
configuration file (such as faces-config.xml), like this:
<validator>
<validator-id>mypkg.CreditCard</validator-id>
<validator-class>mypkg.CreditCardValidator</validator-class> </validator>
You can use custom validators with the f:validator tag—for
example, the following code fragment uses the credit card validator discussed above:
<h:inputText id="card" value="#{payment.card}" required="true"> <f:converter converterId="mypkg.CreditCard"/>
<f:validator validatorId="mypkg.CreditCard"/> </h:inputText>
The validatorId specified for f:validator must correspond to a
validator ID specified in the configuration file. The f:validator tag uses the validator ID to look up the corresponding class, creates an instance of that class if necessary, and invokes its validate method.
Using and Configuring Custom Validator
(using annotation)
Kita dapat menggunakan annotation
@FacesValidator
pada class Custom Validator yg sudah kita buat sbb:
@FacesValidator(“mypkg.CreditCard")
Latihan 04: Modifikasi Converter02
Modifikasilah project di latihan
sebelumnya agar dapat memiliki
mekanisme validasi angka kartu kredit
berdasarkan algoritma Luhn Check
TODO:
1.
Tambahkan annotation @FacesValidator
pada Custom Validator
Latihan 04: screenshots
This validator is using “Luhn” algorithm to check the credit card
numbers. See the documentation provided about this for details.
Tips: try to input