BAB 1 6
St u di Ka su s Aplik a si
Unt uk m em ulai disk usi kit a pada web program m ing, kit a akan m em pert im bangkan sebuah aplikasi sederhana dan m em buat nya dari dasar, m enggunakan sem ua t ool dan t eknik yang t elah dibahas pada m odul- m odul sebelum nya. Kit a akan m enggunakan penget ahuan t ent ang design pat t ern unt uk m em bant u kit a dalam arsit ekt ur int i aplikasi secara fungsional. Kit a akan m enggunakan JDBC API unt uk m em berikan kit a konekt ivit as dengan dat abase yang diperlukan. Unt uk lebih m em anfaat kan archit ect ural dari Model- View - Cont roller, kit a akan m enggunakan fram ework St rut s. Unt uk kom ponen- kom ponen view , kit a akan m enggunakan halam an- halam an JSP dengan beberapa elem en JSTL. Validasi sisi client akan dibuat m enggunakan Javascript .
1 6 .1 I k h t isa r
Aplik a si
Mari kit a awali dengan penj elasan dari keperluan- keperluan aplikasi dari perspekt if t ingkat t inggi.
Pada dasarnya, aplikasi m enyediakan user- usernya dengan daft ar sem inar- sem inar yang t ersedia di dalam inst it usi t ert ent u. Selain m enyediakan j udul dan t opik sem inar, daft ar j uga m enam pilkan t anggal m ulai dan berakhirnya, j adwal unt uk t iap hari, sepert i j uga harga sem inar. User dapat j uga m endapat kan inform asi t am bahan t ent ang m asing- m asing sem inar dalam bent uk deskripsi um um dan garis besar kursus j ika t ersedia.
Berdasarkan inform asi ini, user dapat m em ilih sem inar dim ana bisa m endaft arkan diri. Pem bayaran t idak dilaksanakan secara online; aplikasi diasum sik an bahw a det ail sepert i it u dit angani sendiri oleh user di beberapa w akt u sebelum at au selam a sem inar.
User dapat m engakses kem am puan ini hanya set elah ot ent ikasi sukses oleh sist em . User t idak dapat diot ent ikasi oleh sist em ( cont oh, user m enyediakan det ail account yang t idak ada, user salah ket ik login at au passw ord) , hal ini t idak dapat m em proses halam an berikut nya set elah halam an login.
Aplikasi j uga m enyediakan account adm inist rat if t erpisah dim ana fungsi m anaj em en dapat disediakan unt uk user yang t elah sah. Melalui account adm inist rat if, sem inar- sem inar baru dapat dit am bah, sem inar- sem inar yang t elah ada dapat dim odifikasi. Sem inar dapat j uga dihapus dari sist em , m eskipun hal ini harus diij inkan hanya j ika t idak ada user yang m endaft ar, at au j ika sem inar t elah selesai.
Selain dari m anaj em en sem inar, adm inist rat or j uga harus m em punyai access unt uk beberapa laporan : daft ar sem inar akt if ber kesinam bungan, daft ar siswa yang t erdaft ar per sem inar, sepert i j uga daft ar sem inar dengan siswa yang t idak t erdaft ar.
Sem ua dat a dit erim a kem bali dari dan disim pan ke dalam sebuah dat abase Post greSQL
Masalah- m asalah penggunaan dari aplikasi dapat diringkas dengan use case diagram di bawah:
Mengambil daftar
semina
r
Mendaftarkan
seminar
Mengedit
account user
Menambah user
baru
Menambahkan
seminar
Menghapus
seminar
Retrieve report
Mengedit
seminar
public class SeminarDescription { private int descriptionID; private String title; private String topic; private String description; private String outline; // getters and setters disini }
package jedi.sample.core.bean; public class Seminar {
private SeminarDescription description; private String days;
private String time; private int seminarID; private int slotsLeft;
Mem ungkinkan kit a unt uk m enunj ukkan adm inist rat or dengan obj ek Pegawai, dan hanya m em odifikasi Pegawai sepert i hal it u dapat dengan m udah dit ent ukan j ika it u sebuah Adm inist rat or at au bukan. Hal ini dem ikian karena spesifikasi yang ada t idak benar- benar m em er int ahkan class Adm inist rat or t erpisah. Spesifikasi hanya m em erlukan aplikasi yang berisi konsep dari suat u adm inist rat or. I ni m ungkin akan berubah berikut nya, bagaim anapun, j ika spesifikasi dit ent ukan bahwa class t erpisah perlu ada unt uk m engisi propert ies Adm inist rat or khusus at au m et hod- m et hod.
1 6 .3 M e m bu a t
M ode l
Karena kit a ingin m enggunakan pola desain Model- View - Cont roller, sebaiknya kit a m endesain class- class dalam pik iran kit a sebelum nya. Dengan ini, berart i kit a m em buat class- class int i kit a
yang secara fungsional m ereka ungkapkan t idak t erikat dalam beberapa im plem ent asi int erface.
Terdapat beberapa pendekat an yang m em ungkinkan unt uk m engem bangkan class- class kit a. Dalam pem belaj aran ini, kit a m em ilih unt uk m elakukan pendekat an berlapis : m endefinisikan beberapa lapisan abst raksi dan bekerj a dari lapisan t erat as ke bawah.
Database
Data Access Layer
Facade Layer
Lapisan m enurun dari at as ke bawah. Arah dari pendekat an kit a – dari lapisan t ert inggi – m em punyai alasan logis dibelakangnya, yang selanj ut nya akan m enj adi nyat a.
Diagram di at as m enunj ukkan konsep lapisan class- class int i kit a. Menggunakan dua lapisan : sat u unt uk m em perkenalkan int erface sederhana unt uk beberapa client yang akan m enggunakan fungsionalit asnya, yang lainnya unt uk int erfacing dengan penyim panan persist ent. Kedua lapisan berdasarkan design pat t erns yang sudah kit a bahas sebelum nya : Dat a Access Obj ect pat t ern, dan Facade pat t ern.
Kit a m enggunakan lapisan obj ek Dat a Access unt uk m em isahkan det ail im plem ent asi penghubungan ke ekst ernal dat a source. Hal ini m em buat kit a lebih flexibel unt uk selanj ut nya. Lapisan Facade obj ect diperlukan sehingga client code yang m enggunakan class- class int i t idak perlu unt uk m enam pilkan m et hod- m et hod secara langsung pada obj ek dom ain. Unt uk inform asi, lihat pada bab sebelum nya di Design Pat t ern.
Alasan bekerj a dari lapisan Facade m enurun karena hal ini lebih m udah unt uk m endefinisikan m et hod pada facade obj ect bersam a use case dan bekerj a dari sana daripada bekerj a dari lapisan abst raksi t erendah dan m em buat perkiraan yang m endidik sepert i yang aplikasi akan but uhkan.
Unt uk aplikasi kit a, kit a m em buat dua Facade obj ect : sebuah UserFacade yang akan m engendalikan sem ua fungsi- fungsi user- relat ed t erm asuk pem buat an dan ot ent ikasi; dan sebuah Sem inarFacade obj ect yang akan m engendalikan use case m engenai sem inar. Kit a m ungkin bisa m em ecahkan use case aplikasi kit a pada cara yang berbeda: ini adalah pilihan desainer bagaim ana m elakukannya, selam a sem ua use case t ercakup dan m engelom pokkannya berdasarkan t em a logis. Disini, t em a kit a adalah unt uk m engelom pokkan use case berdasarkan area dom ain dim ana m ereka bekerj a. Tem a lain yang m em ungkinkan adalah unt uk m engelom pokkan use case berdasarkan part isipasi akt or ut am a pada aplikasi.
package jedi.sample.core; public class UserFacade { // tambahkan method disini }
1 6 .3 .1 Be k e r j a pa da use ca se Add ne w u se r
Hal ini m udah unt uk m engem bangkan aplik asi sat u use case pada wakt u yang sam a, dengan m elakukannya m aka m enyediakan developer sebuah pandangan yang j elas dari apa yang dibut uhkan. Kit a m em ulai berbagai hal dengan m em pert im bangkan use case " Add new user" .
Pert am a, m ari kit a t am bahkan sebuah m et hod ke UserFacade m enyesuaikan pada use case ini. Kit a akan m eninggalkan im plem ent asi sepert i j uga deklarasi param et er kosong unt uk sekarang; kit a akan m em odifikasinya bersam a.
package jedi.sample.core; public class UserFacade { public void addNewUser() {
// implementasi kosong untuk sekarang. }
}
Set elah m enyelesaikan keperluan use case, m et hod ini harus dapat m encipt akan m asukan unt uk user baru pada persist ent st orage kit a. I ni secara logika m enyirat kan bahw a m et hod ini harus m em berikan sem ua dat a yang akan diperlukan pada pem buat an user baru. Secara um um ini m erupakan sebuah ide bagus unt uk m enyediakan beberapa m acam feedback pada m asing-m asing fungsi dari class- class int i yang akan asing-m engij inkan code client unt uk asing-m enget ahui apkah sebuah operasi t elah sukses at au t idak.
Sebagai gant i coding sem ua propert ies user sebagai param et er dalam m et hod kit a, kit a m em pelaj ar i dar i t ransfer obj ect pat t ern dan m em berik an dat a yang diperlukan sebagai obj ek. Kit a dapat hanya dengan m enggunakan User dom ain obj ect yang t elah ada daripada t ransfer obj ect yang t erpisah, karena hal it u m enangkap sem ua dat a yang kit a but uhkan. Mem perbarui m et hod, kit a m em ilik i :
...
1 6 .3 .2 M e m bu a t im ple m e n t a si fa ca de u n t u k use ca se Add Use r
Tuj uan dari m et hod ini adalah unt uk m em buat m asukan unt uk user baru pada persist ent st orage. Dasar dari im plem ent asi kit a kem udian akan m enj adi suat u panggilan pada dat a access obj ect yang akan m elaksanakan operasi t ersebut . Spesifikasi kit a sekarang t idak m em int a lagi.
Sekarang, kit a hanya m em buat int erface unt uk dat a access obj ect , kit a dapat m enggunakan dan m eninggalkan im plem ent asinya kem udian. Sej auh ini, inilah yang kit a m iliki :
package jedi.sample.core.dao; import jedi.sample.core.bean.User; public interface UserDAO {
public boolean createNewUser(User user); }
Kit a dapat m em ilih unt uk m endapat kan kem bali inst ance dari int erface facade kit a yang m anapun dengan coding secara det ail, langsung ke dalam facade, at au dengan m eringkas det ail- det ail t ersebut ke dalam class fact ory. Unt uk fleksibilit as yang selanj ut nya diperbaiki, kit a m enggunakan class fact ory.
Met hod kit a pada UserFacade sekarang t erlihat sepert i ini :
...
public boolean addNewUser(User user) {
UserDAO dao = DAOFactory.getUserDAOInstance(); return dao.createNewUser(user);
}
Code unt uk DAOFact ory akan dit unda hingga kit a selesai m em buat im plem ent asi awal kit a dar i int erface UserDAO.
1 6 .4 M e n gim ple m e n t a sik a n
Use r D AO
Hal pert am a yang dilakukan adalah m em buat definisi class yang m engim plem ent asikan int erface UserDAO dan m et hod- m et hod yang dibut uhkan
package jedi.sample.core.dao; import jedi.sample.core.bean.User;
public class UserPostgreSQLDAO implements UserDAO { public boolean createNewUser(User user) {
// implementasi kita disini }
}
Salah sat u persayarat an m ut lak dari beberapa dat a access obj ect adalah suat u cara unt uk berkom unikasi dengan ext ernal dat a source. Karena DAO disesuaikan dengan im plem ent asi dat abase Post greSQL, hal ini berart i bahw a class ini m em but uhkan inst ance dari obj ek Connect ion.
Dari diskusi- diskusi kit a sebelum nya, kit a m enget ahui bahwa kit a dapat m enyediakan obj ek Connect ion ini yang m anapun dengan m endapat kannya kem bali dari m et hod st at ic pada class DriverManager, at au dengan m endapat kannya kem bali lewat panggilan JNDI dari sebuah kont eks ekst ernal sebagai suat u Dat aSource. Pilihan kedua adalah m erupakan salah sat u yang m enawarkan paling fleksibilit as dan kem udahan pem eliharaan, sehingga hal it u akan m enj adi pilihan kit a.
Mem pert im bangkan fakt or- fakt or yang disiapkan di at as, kit a m engim plem ent asikan pem bacaan Dat aSource kit a sepert i dem ikian :
package jedi.sample.core.dao; import jedi.sample.core.bean.User; import javax.sql.DataSource; import javax.naming.*;
public class UserPostgreSQLDAO implements UserDAO { private static DataSource ds = null;
static { try {
Context ctxt = new InitialContext();
ds = (DataSource)ctxt.lookup("jdbc/sampleDataSource"); } catch (NamingException e) {
throw new }
}
public boolean createNewUser(User user) { // implementasi kita disini
} }
Set elah kit a m em punyai sebuah inst ance Dat aSource yang valid yang siap dan m enunggu, sekarang kit a dapat m enulis im plem ent asi dari m et hod creat eNewUser.
...
public boolean createNewUser(User user) { if (ds == null) {
Baris kodenya :
return stmt.executeUpdate(sql) > 0
Mengem balikan nilai t r ue j ika t erdapat baris yang disebabkan oleh eksekusi pernyat aan ( insert sukses) , dan m engem balikan nilai false j ika t ida t erdapat baris yang disebabkan ( insert gagal) .
Pengeksekusian dari m et hod close pada class- class JDBC yang di- inst ant iat e dit em pat kan dalam blok finally code unt uk m em ast ikan bahw a m ereka m elaksanakannya t erus m enerus, kondisi sukses at au t idak, error yang t erduga at au t idak. Dengan m elakukan dem ikian, kit a m em ast ikan bahwa aplikasi selalu m erilis dat abase yang berhubungan dengan resourcenya. Jika t idak m elakukannya, secara negat if akan m em pengaruhi kinerj a aplikasi, belum lagi m ungkin m em buat seluruh aplikasi akan berhent i karena ket iadaan resource yang m eng- execut e operasi baru selanj ut nya.
1 6 .4 .1 Pe n u lisa n k ode D AOFa ct or y
Akhirnya, kit a m enghasilkan class fact ory yang bert anggung j awab dalam pem buat an inst ance-inst ance dari int erface- int erface DAO yang digunakan oleh aplikasi kit a. Secara um um , kit a t idak harus m em buat inst ance nyat a dari class fact ory it u sendiri unt uk dapat m em buat inst ance-inst ance dari DAO- DAO kit a. Hal ini m enyir at kan bahwa kit a m engem bangkan m et hod- m et hod kit a m enj adi m et hod- m et hod st at ic.
package jedi.sample.core.dao; public class DAOFactory {
public static UserDAO getUserDAOInstance() { return new UserPostgreSQLDAO();
1 6 .4 .2 Be k e r j a pa da use ca se ya n g be r be da
Set elah kit a m enyelesaikan pengem bangan use case " Add New User" , kit a dapat m elanj ut kan ke use case lain yang perlu kit a im plem ent asikan. Use case berikut nya yang kit a am bil adalah use case " Get Sem inar List " . Karena kit a bekerj a pada kum pulan dari dat a sem inar, kit a m enam bahkan sebuah m et hod baru unt uk obj ek Sem inarFacade kit a. Sebagai suat u pengingat , salah sat u dari keput usan- keput usan aw al desain kit a adalah unt uk m em bagi use cases kit a sepanj ang facade yang berbeda berdasarkan kum pulan dat a dom ain dim ana m ereka bekerj a.
package jedi.sample.core; import jedi.sample.core.dao.*; public class SeminarFacade {
public Collection getSeminarList() {
SeminarDAO dao = DAOFactory.getSeminarDAOInstance(); return dao.getSeminarList();
} }
Pert im bangan- pert im bangan design unt uk im plem ent asi dari m et hod get Sem inarList adalah sam a sepert i yang dit em ui pada m et hod addNewUser : t uj uan dari m et hod adalah unt uk m elaksanakan operasi pada dat a source ekst ernal ( saat pem bacaan dat a) . Melihat spesifikasi kit a, kit a m elihat bahwa t idak t erdapat operasi lain yang dibut uhkan unt uk m et hod kit a unt uk dilaksanakan sepert i yang dibut uhkan.
Disini, m et hod kit a m engem balikan inst ance dari int erface Collect ion yang akan berisi obj ek- obj ek Sem inar m ewakili daft ar sem inar- sem inar yang t ersedia. Sebagai alt ernat if, kit a dapat m engem balikan obj ek- obj ek Sem inar sebagai suat u array; bagaim anapun, akan m enam bah kesulit an unt uk m elakukannya, yang akan kit a lihat selanj ut nya.
I nt erface unt uk Sem inarDAO dapat didefinisik an sepert i :
package jedi.sample.core.dao.*;
import jedi.sample.core.bean.Seminar; public interface SeminarDAO {
public Collection getSeminarList(); }
1 6 .4 .3 M e n gga li fu n gsi um um la in ny a
I m plem ent asi Post greSQL kit a dari Sem inarDAO dan UserDAO, karena t erpaksa, m em punyai kesam aan. Hal it u karena m ereka berbagi kem am puan : keduanya m em erlukan akses ke dat abase unt uk fungsi sepert i yang t elah didesign. Jadi, kode koneksi dat abase dapat dit em ukan pada keduanya. Secara t erperinci, area dim ana m ereka akan bersam a- sam a m em baca inst ance Dat aSource yang valid, sepert i j uga m elepasan ( realease) resource set elah digunakan.
import javax.naming.*;
public Connection getConnection() throws SQLException{ if (ds == null) return null;
return ds.getConnection(); }
Menggunakan class di at as sebagai dasar, code kit a unt uk im plem ent asi UserDAO m enj adi lebih sederhana :
public class UserPostgreSQLDAO extends DataAccessObject implements UserDAO { public boolean createNewUser(User user) {
Connection conn;
Kit a m em buat im plem ent asi Sem inarDAO kit a unt uk m engam bil kunt ungan dari class dasar yang kit a design sebelum nya :
package jedi.sample.core.dao;
import jedi.sample.core.bean.Seminar;
import jedi.sample.core.bean.SeminarDescription; import java.util.*;
public class SeminarPostgreSQLDAO extends DataAccessObject implements SeminarDAO { public Collection getSeminarList() {
Connection conn = null; Statement stmt = null;
ResultSet rs = null;
try {
Karena kit a t idak harus m eniru code pada bagaim ana m andapat kan kem bali Dat aSource dan bagaim ana unt uk m enut up resource dat abase dengan baik, kit a dapat m em usat kan perhat ian kit a pada m et hod kit a unt uk m elaksanakan kem am puan yang dibut uhkan.
Unt uk m endapat kan kem bali daft ar sem inar pada dat abase besert a deskripsinya, m et hod kit a m enggunakan pernyat aan SQL berikut :
"SELECT * FROM seminars inner join seminardescriptions using(descriptionid)"
Hasil dari pernyat aan SQL ini kem udian didapat kan kem bali m enggunakan obj ek Result Set . Kit a m engulangi pada m asing- m asing baris dari hasil, t iap kali m engenkapsulasi dat a yang kit a but uhkan ke dalam obj ek- obj ek yang kit a definisikan sebelum nya.
Sebelum nya, dij elask an bahwa hal t ersebut lebih m udah unt uk m engim plem ent asikan pengem balian dat a m enggunakan inst ance dari int erface Collect ion dibandingkan dengan m enggunakan array dari obj ek- obj ek t ransfer. Alasannya adalah int erface Result Set t idak m enyediakan m et hod yang akan m engem balikan banyaknya baris- baris unt uk didapat kan kem bali. Tanpa inform asi ini,kit a t idak dapat m em buat array yang kit a but uhkan sebelum m em ulia proses pengulangan. Beberapa im plem ent asi int erface Collect ion sepert i Vect or dan ArrayList , di sisi lain, m enyediakan m et hod sederhana yang m em ungkinkan Anda unt uk m enam bah obj ek- obj ek t anpa harus m enspesifikasikan banyaknya obj ek yang m ereka but uhkan unt uk di isi.
1 6 .4 .5 M e r in gk a s se j a uh a pa ya n g t e la h k it a la k uk a n
I m plem ent asi kedua use case yang t elah kit a lakukan sej auh ini m enyert akan keput usan-keput usan design yang akan digunakan unt uk sisa dari use case yang lain. Unt uk m enj um lahkan m ereka :
• Kem am puan int i adalah diakses dari lapisan obj ek facade. Kit a m engelom pokkan facades kit a berdasarkan t em a logis. Pada aplikasi kit a, kit a m em buat sebuah facade unt uk m asing- m asing dat a dom ain dit et apkan penggunaan. ( UserFacade, Sem inarFacade)
• Unt uk m endapat kan kem bali dat a dari sum ber ekst ernal, aplikasi k it a m enggunakan Dat a Access Obj ect pat t ern. Kit a m em buat obj ek- obj ek dat a access berbeda unt uk dat a dom ain berbeda dit et apkan unt uk m enghindari class all- in- one yang m ungkin akan m em bengkak di kem udian.
• Kem am puan obj ek dat a access diekspos ke lapisan facade lewat int erface- int erface yang kit a desain. Facade m em peroleh inst ance yang dapat dikerj akan dari int erface ini lew at obj ek Fact ory yang berisi det ail- det ail dari inst ant iat ion.
• I m plem ent asi- im plem ent asi m ungkin ada yang berbeda unt uk int erface DAO berdasarkan sum ber dat a dim ana DAO m elaksanakan operasi- operasinya. Sebuah im plem ent asi yang yang m endapat kan kem bali dat a dari dat abase berbeda dari im plem ent asi yang m endapat kannya kem bali dar i sum ber lain, sepert i sebuah server LDAP sebagai cont oh. • Kit a m enggunakan int erface Collect ion sebagai t ipe pengem balian dari m et hod- m et hod
pada lapisan dat a access ( dan m ungkin lapisan facade) yang m endapat kan kem bali penent uan dat a. Dim ana im plem ent asi int erface Collect ion ( Vect or, ArrayList , ...) digunakan di dalam im plem ent asi DAO, hal it u t erserah developer.
• Unt uk operasi- operasi dat a yang t idak m endapat kan kem bali dat a (insert ions, updat es, delet ion) , kit a m enyediakan sebuah m ekanism e unt uk feedback yang dapat digunakan dengan beberapa client m enggunakan kem am puan int i kit a. Pada aplikasi kit a, kit a m enggunakan t rue at au false unt uk m enandakan sebuah operasi sukses at au gagal. Feedback lain yang m ungkin m engukur akan m engem balikan code- code st at us unt uk m engindikasikan berm acam - m acam level dari sukses at au gagal.
1 6 .5
M e m bu a t k om pon e n V ie w da n Con t r olle r .
Set elah m em buat class- class yang m engim plem ent asikan kem am puan int i ( m odel) , kit a dapat m eneruskan sisa aplik asi web kit a. Sekarang kit a dapat m em buat int erface web m enggunakan halam an- halam an JSP ( view ) dan m enggunakan class- class dan m engkonfigurasikan file- file yang disiapkan oleh fram ew ork unt uk m engim plem ent asikan aliran aplikasi ( cont roller) . Tidak sepert i m odel, dim ana kit a dapat m engem bangkan sebagai suat u kom ponen independent dari aplikasi kit a, kom ponen view dan cont roller diikat bersam a- sam a, m engharuskan kit a m engem bangkannya dalam berurut an.
1 6 .5 .1 M e m bu a t h a la m a n login
Salah sat u t em pat t erbaik unt uk m em ulai m em buat aplikasi w eb kit a adalah layar loginnya, sebagai penunj uk inisial user dari m asukan unt uk aplikasi kit a. Sebuah layar login dapat dengan m udah m enj adi sebuah form pert anyaan unt uk nam a login user dan passw ord, set elah m elaluinya unt uk m ekanism e ot ent ikasi user.
Kit a m em buat layar login kit a m enggunakan halam an JSP, m enggunakan t ag library yang disediakan oleh St rut s unt uk m em buat form HTML :
<%-- styleId renders an id attribute for the form element --%>
<td><html:text styleId="userName" property="userName"/></td> </tr>
<tr>
<td>Password : </td>
<td><html:password styleId="password" property="password"/></td> </tr>
<tr>
<td colspan="2"><html:submit value="Login"/></td> </tr>
</html:form> </table>
1 6 .5 .2 M e m bu a t Act ion For m u n t u k ha la m a n login .
Sebelum m em buat Act ion handler unt uk form ini, pert am a kit a m em buat Act ionForm yang akan m enangkap m asukan user. Kit a dapat dengan m udah m elakukan ini dengan m enggunakan Net Beans 5's built - in yang m endukung unt uk St rut s. Sebagai suat u t inj auan ulang, langkah-langkah unt uk m em buat Act ionForm baru di Net Beans 5 adalah :
• Klik- kanan pada direct ory Source Packages di Proj ect view • Pilih New - > File/ Folder
• Di baw ah Web cat egory, pilih St rut s Act ionForm bean.
• Tent ukan nam a dan package unt uk digunakan dalam pem buat an Act ionForm .
Unt uk form yang ada, kit a m enam akannya LoginForm , dan m enem pat kannya dalam package j edi.sam ple.st rut s.form . Set elah Net Beans m en- generat e class, kit a m enghapus field- field dan m et hod- m et hod yang t elah digenerat e. Kem udian, kit a t am bahkan dalam field- field yang kit a but uhkan unt uk m enangkap input an user. Mereka dinam ai sam a dengan value- value pada at ribut propert i yang dit em ukan pada form kit a, berart i kit a m enam bahkan ke dalam field- field userNam e dan password unt uk LoginForm bean.
Unt uk m enam bahkan validasi yang selanj ut nya akan m endukung, kit a m engubah class dasar dari Act ionForm kit a dari package org.apache.st rut s.act ion.Act ionForm m enuj u pada package org.apache.st rut s.validat or.Validat orForm .
1 6 .5 .3 M e m bu a t a ct ion h a ndle r ha la m a n login
Set elah m em buat Act ionForm , kit a m em buat Act ion yang akan m enangani subm isi form . Tam bahan, sebuah t inj auan ulang pem buat an Act ion m enggunakan Net Beans :
• Klik kanan pada direct ory Source Packages pada Proj ect view • Pilih New - > File/ Folder
• Di baw ah Web Cat egory, pilih St rut s Act ion, klik pada Next
• Buka halam an at au act ion yang akan m enj adi asal- m uasal dari pem anggilan ke act ion ini. ( Dalam hal ini, act ion kit a akan dipanggil oleh sebuah subm isi form pada halam an login.j sp)
• Klik Finish.
Set elah m em punyai class dan konfigurasi dat a yang dihasilkan oleh Net Beans, kit a m engim plem ent asikan kem am puan dalam m et hod yang m engeksekusinya. Pada dasarnya, apa yang kit a perlukan pada act ion handler kit a adalah sesuat u yang akan m engam bil input user ( nam a user dan password) , dan m enyediakannya sebagai param et er unt uk m ekanism e ot ent ikasi yang disediakan dalam kem am puan int i kit a. Pot ongan code di baw ah m enunj ukkan hal ini:
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
LoginForm loginForm = (LoginForm)form;
UserFacade facade = new UserFacade();
// the authenticateUser method returns either a valid User instance if user is properly // authenticated, or null if not.
User user = facade.authenticateUser(loginForm.getUserName(), loginForm.getPassword());
Begit u kit a m endapat kan kem bali obj ek User yang m ewakili user, apa yang dilakukan berikut nya? Pert am a, kit a m em er ik sa j ika obj ek user yang kit a dapat kan kem bali adalah keadaan yang valid. Dengan kat a lain, kit a m em eriksa j ika cr edent ials yang disediakan oleh user m engij inkan unt uk m em proses sisa aplikasi. Jika user t idak secara baik diot ent ikasi, solusi paling um um adalah m engem balikan user ke layar login, dengan pesan yang m enginform asikan hasil:
...
if (user == null) {
ActionMessages messages = new ActionMessages(); messages.add("login error",
new ActionMessage("invalid.user.account")); saveMessages(request, messages);
return mapping.getInputForward(); }
Jika hal t ersebut t erlupakan, St rut s m enggunakan file propert ies unt uk m enyim pan pesan t ersebut . St ring " invalid.user.account " bukan pesan nyat a yang aplikasi t am pilkan; hal t ersebut hanyalah kunci yang m enandakan nilai pada file propert ies yang digunkan unt uk pesan. Kit a akan m em buat pesan nyat a selanj ut nya.
Sej auh ini, kit a sudah m encakup dim ana user t idak secara baik diaut ent ifikasi. Apa yang t erj adi kem udian j ika user m elewat i ot ent ikasi? Pendekat an paling logis adalah unt uk m em bawa user ke layar selanj ut nya pada aplikasi. Sebelum m enam pilkan arah kem bali, adalah ide yang bagus m enam pilkan inisialisasi user- specific. Sebagai cont oh, lat ihan um um adalah m enyim pan inform asi user ke dalam session sehingga aplikasi t idak harus m endapat kannya kem bali di lain w akt u.
Berikut ini LoginAct ion lengkap kit a:
public class LoginAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
throws Exception {
User user = facade.authenticateUser(loginForm.getUserName(), loginForm.getPassword());
session.setAttribute(JEDIConstants.USER_SESSION, user);
return mapping.findForward("success"); }
}
Class JEDI Const ant s digunakan di at as m erupakan class sederhana yang digunakan unt uk m em egang const ant s yang akan digunakan pada aplikasi. Unt uk sekarang, class didefinisikan m enj adi :
public class JEDIConstants {
public final static String USER_SESSION = "userObject"; }
Const ant s lain dapat dit am bahkan selanj ut nya, sepert i yang aplikasi but uhkan.
1 6 .5 .4 Be r m a ca m - m a ca m a k t ivit a s u nt u k m e n gim ple m e n t a sik a n la ya r login
Sej auh ini, pada pem buat an halam an login, kit a t elah m elaksanakan akt ivit as berikut : • Mem buat halam an JSP yang m endukung definisi form kit a.
Unt uk m em ilik i im plem ent asi m inim al dar i halam an login yang dapat berj alan, akt ivit as berikut m asih perlu unt uk dilaksanakan :
• Mendefinisikan " success" unt uk LoginAct ion yang m enunj ukkan ke layar berikut nya pada aplikasi.
• Menam bahkan m asukan pada file propert ies Applicat ionResources unt uk pesan error yang akan dit am pilkan ke user pada pengirim an account yang t idak valid.
1 6 .5 .5 M e n a m ba hk a n se bua h Act ion For w a r d
Di at as kit a dapat m elihat bahw a Act ionForward didefinisikan m enj adi lokal unt uk LoginAct ion, dan t idak t am pak secara global. Hal ini karena nam a forw ard adalah success yang berart i ket ika t am pak ke keseluruhan aplikasi: " success" dapat berart i banyak hal unt uk aplikasi kit a, bergant ung pada Act ion yang akan m enggunakan forw ard. Kit a hanya m em buat global Act ionForw ards ket ika m ereka m endefinisikan layar at au act ion yang berart i unt uk keseluruhan ( sedikit nya unt uk kebanyakan dari) aplikasi k it a. Yang lain seharusnya didesain m enj adi global sehingga hanya Act ion yang sesungguhnya yang m em but uhkan definisi yang dapat m enggunakannya.
1 6 .5 .6 M e n a m ba hk a n m a su k a n pa da file pr ope r t ie s Applica t ionRe sou r ce s
Pada loading file propert ies default yang dihasilkan oleh Net Beans, kit a m enem ukan bahw a t elah ada sej um lah besar m asukan. Kit a hanya m enam bahkan isi di baw ah ini pada akhir :
Invalid.user.account=No user exists with the supplied credentials.
1 6 .5 .7 M e n a m ba hk a n va lida si LoginFor m k it a
Beberapa form t idak seharusnya dipert im bangkan lengkap t anpa sedikit nya sat u form dari validasi input . Mem ast ikan input benar/ valid m em ast ikan out put benar. Pada aplikasi ini, kit a m enam bahkan dua validasi pada LoginForm kit a: validasi sisi client dan sisi server.
1 6 .5 .7 .1 V a lida si sisi clie n t
Unt uk m elaksanakan validasi sisi client , kit a m enam bahkan script di baw ah ke dalam JSP :
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %> <script>
function validateInput() {
var userNameField = document.getElementById("userName"); var passwordField = document.getElementById("password");
var errorMessage = "";
if (userNameField.value == "") {
errorMessage += "<bean:message key="errors.username.missing"/> .\n"; }
if (passwordField.value == "") {
JavaScript pada cont oh ini sederhana : hanya m em verifikasi kedua fields pada form yang diberikan nilai dan m enam pilkan pesan error j ika sedikit nya sat u dari m ereka kosong. Script dapat m engident ifikasi m asing- m asing elem en form dengan m enunj uk id keduanya. I D ini diberikan unt uk fields m elalui at ribut st yleI d:
<tr>
<td>User Name : </td>
<td><html:text styleId="userName" property="userName"/></td> </tr>
<tr>
<td>Password : </td>
<td><html:password styleId="password" property="password"/></td> </tr>
Pesan error t idak secara langsung dit uliskan dalam JSP. Sebagai gant inya kit a m endapat kan kem bali dar i file proper t ies dim ana St rut s m enyim pan pesan t ersebut . Dengan m em punyai pesan error pada file pr opert ies m em buat nya t ersedia selanj ut nya unt uk code validasi sisi server kit a. Hal ini akan m em ast ikan validasi sisi client dan sisi server akan m enam pilkan pesan yang sam a.
Unt uk m em ilik i script yang m em validasi input sebelum pengirim an form , kit a m em odifikasi JSP kit a sehingga akan m em anggil fungsi dim anapun user m engklik pada t om bol pengirim an.
<tr>
<td colspan="2"><html:submit value="Login" onclick="return validateInput();"/></td> </tr>
1 6 .5 .7 .2 M e n a m ba hk a n va lida si sisi se r ve r
Melaksanakan j enis validasi yang sam a pada sisi server unt uk form ini adalah m udah j ika kit a m enggunakan St rut s Validat or fram ework. Unt uk m em eriksa input an form pada field userNam e dan password, Kit a m em buat m asukkan unt uk LoginForm di dalam validat ion.xm l yang m engkonfigurasi dan m enspesifikkan bat asan " yang diperlukan" oleh keduanya.
<form-validation> <formset>
<form name="LoginForm">
<field property="userName" depends="required"> <arg key="errors.username.missing"/>
</field>
<field property="password" depends="required"> <arg key="errors.password.missing"/>
1 6 .5 .8 V ie w Se m in a r List Pa ge
Persyarat an lain unt uk aplikasi kit a adalah halam an yang dapat m enem pilkan sem ua sem inar yang ada. Sepert i halam an yang dapat dengan m udah dibangun dengan m enggunakan view helpers dan JSTL :
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> <jsp:useBean id="seminarHelper" scope="session"
class="jedi.sample.helper.SeminarViewHelper"/> <table border="2">
<tr>
<td>Title</td> <td>Topic</td> <td>Days</td> <td>Time</td> <td>Cost</td> </tr>
<c:forEach items="${seminarHelper.seminarList}" var="seminar"> <tr>
<td>${seminar.description.title}</td> <td>${seminar.description.topic}</td> <td>${seminar.days}</td>
<td>${seminar.time}</td> <td>${seminar.cost}</td> </tr>
</c:forEach>
Disini, kit a m enggunakan pola desain View Helper dan m enggunakan sebuah bean unt uk m em isahkan pem bacaan daft ar rincian sem inar. Sem ua JSP kit a sekarang perlu m endapat kan daft ar unt uk m em anggil pada m et hod di helper dan it erasi lebih dari daft ar yang diberikan m enggunakan JSTL.
View helpers t idak perlu diperum it . Sering kali m ereka m erupakan class- class yang sangat private Collection seminarList; private SeminarFacade facade;
public Collection getSeminarList() { seminarList = facade.getSeminarList(); return seminarList;
} }
View helper t idak perlu m em iliki im plem ent asi sendiri dalam pem bacaan dat a. Kit a dapat j uga m em buat view helpers sepert i dim ana m ereka m enaikkan fungsi- fungsi yang t elah ada dalam class- class int i kit a. Dalam kasus di at as cont ohnya, class Sem inarViewHelper m enangani dirinya sendiri sebagai sebuah inst ance dari obj ek Sem inarFacade dim ana kit a kem bangkan sebelum nya. Menggunakan inst ance ini, dapat m engakses dat a khusus sem inar / operasi, sepert i m endapat kan kem bali sebuah daft ar dari sem inar- sem inar yang ada di dat abase. I t u j uga m em elihara cache dari sem inar yang t erakhir m endaft ar dalam dirinya. Sem ent ara it u t idak m enghasilkan unt uk kinerj a t am bahan at au kem am puan unt uk halam an pem bacaan daft ar sem inar, it u m enyederhanakan hal- hal unt uk halam an selanj ut nya yang akan diliput , halam an det ail sem inar.
1 6 .5 .9 H a la m a n D e t a il Se m in a r
Di dalam spesifikasi aplikasi kit a, t erkecuali m am pu m endapat kan kem bali daft ar sem inar, seorang user harus m am pu m em peroleh inform asi t erperinci t ent ang m asing- m asing sem inar. Menam pilkan m acam - m acam inform asi yang t erperinci, dapat diim plem ent asik an pada halam an yang t erpisah. User kem udian m em peroleh akses unt uk halam an " det ail" khusus dengan m engklik pada link yang dihubungkan dengan m asing- m asing sem inar.
Unt uk dapat m enerim a at au m enam pilkan sebuah sem inar khusus, kit a m em but uhkan kem am puan unt uk m engident ifikasi secara unik (uniquely ident ify) sem inar yang dipert anyakan. Hal ini dapat dilakukan dengan m elayani I D sem inar : m asing- m asing sem inarI D m enunj ukkan inst ance unique Sem inar. Mem pert im bangkan hal ini, kit a dapat m em odifikasi Sem inarViewHelper kit a unt uk m elaksanakan sem acam pem bacaan:
package jedi.sample.helper; import java.util.Collection;
import jedi.sample.core.SeminarFacade;
public class SeminarViewHelper { private Collection seminarList; private SeminarFacade facade; private int seminarID;
public Collection getSeminarList() { seminarList = facade.getSeminarList(); return seminarList;
}
View helper kit a sekarang dapat m engam bil nilai sem inarI D dim ana dapat digunakan unt uk m endapat kan kem bali sem inar spesifik dar i dalam daft ar chachenya. Jika user t idak m enyediakan sem inarI D, at au j ika sem inar dengan sem inarI D yang diberikan t idak dapat dit em ukan pada daft ar, it u akan m engem balikan obj ek null unt uk m enandakan kegagalan. Sem inarI D m engat ur ulang ke st at us 0 set elah m asing- m asing pem bacaan operasi, berhasil at au t idak. I ni m em ast ikan bahw a rincian hanya akan t ersedia j ika sem inarI D t elah diberikan dan bahw a sem inarI D bukan "cached" dalam helper.
Kit a sekarang m em iliki kem am puan yang kit a but uhkan dalam view helper kit a. Hanya rincian yang dit inggalkan unt uk m engim plem ent asikan bagaim ana m enyediakan sem inar I D yang sesuai unt uk penggunaan helper, dan bagaim ana m em indahkan kendali dari halam an daft ar sem inar ke dalam halam an det ail.
Dua det ail ini dapat dipecahkan dengan m engim plem ent asikan sebuah link em bedded di dalm m asing- m asing it em dalam daft ar sem inar.Link ini m enunj ukkan browser pada halam an det ail pada wakt u yang sam a m enyediakan sebuah param et er sem inar I D yag sesuai dengan it em yang dipilih. Modifikasi dari sem inarList .j sp, sepert i berikut :
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<c:forEach items="${seminarHelper.seminarList}" var="seminar"> <tr>
<td><html:link forward="seminarDetail" paramId="seminarID" paramName="seminar" paramProperty="seminarID">
${seminar.description.title}
</html:link></td>
<td>${seminar.description.topic}</td> <td>${seminar.days}</td>
<td>${seminar.time}</td> <td>${seminar.cost}</td> </tr>
</c:forEach>
Karena sekarang kit a dapat m endapat kan kem bali sem inarI D yang sesuai dari param et er request , m enyediakannya ke dalam view helper sem udah m enggunakan JSPs built - in act ions unt uk m endukung JavaBean. Set elah m enyediakan sem inar I D, obj ek Sem inar dapat didapat kan kem bali, dan det ailnya dit am pilkan.
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> <jsp:useBean id="seminarHelper" scope="session"
class="jedi.sample.helper.SeminarViewHelper"/>
<jsp:setProperty name="seminarHelper" property="seminarID"/>
<c:set var="seminar" value="${seminarHelper.seminar}"/> <c:choose>
<c:when test="${! empty seminar}"> Seminar Details :
<table border="2"> <tr>
<td>Title</td>
<td>${seminar.description.title}</td> </tr>
<tr>
<td>Topic</td>
<td>${seminar.description.topic}</td> </tr>
<tr>
<td>Description</td>
<td>${seminar.description.description}</td> </tr>
</c:when> <c:otherwise>
No seminar has been specified or given seminar does not exist </c:otherwise>
1 6 .6 Ke sim pu la n
Pada diskusi kit a dalam pem buat an int erface web aplikasi kit a, kit a t elah m engerj akan bagaim ana m em buat sebuah form yang m endapat kan kem bali input an dari user dan forw ards cont rol ke layar berikut nya. Kit a j uga t elah m elihat bagaim ana kit a dapat m elakukan validasi pada form dengan JavaScript pada sisi client dan fram ework Validat or pada sisi server. Kit a t elah m am pu m endapat kan kem bali inform asi daft ar dari dat abase, dan bagaim ana m em buat halam an det ail dapat m enam pilkan dat a yang t erperinci pada it em yang spesifik dari daft ar t ersebut .