BAB 16 Studi Kasus Aplikasi - JENI Web Programming Bab 16 App Case Study
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. Adm inist rat or j uga dapat m enam bah account user baru; t idak ada kem am puan m endaft arkan diri sendiri dalam aplikasi ini. Pert anyaan bagaim ana user diberit ahukan t ent ang det ail account nya adalah di luar lingkup aplikasi. Kem am puan unt uk m engedit user account yang t elah ada diberikan oleh adm inist rat or dan oleh user account nya sendiri.
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 Menambah user semina r baru
Mendaftarkan Menambahkan seminar seminar
Mengedit account user Admin Menghapus seminar Mengedit seminar Retrieve report
Dom ain m odel unt uk aplikasi ini j uga cukup sederhana :
1* manages
User Seminar Administrator
1 registers for
1
- firstName
- days
1*
- middleName
- slots
1
- lastName
- time
1
is a
- address
- emailAdd 1* Employee - contactNumber
manages describes has a
- firstName
1
- middleName
1*
1
- lastName
registered in contains
SeminarDescription
1 1*
- title
- topic SeminarClassList
- description
1*
1
- outline
1 6 .2 M e m bu a t dom a in obj e ct
Unt uk m em ulai berbagai hal, m ari kit a pert am a m em buat dom ain obj ect yang kit a ident ifikasi m enggunakan dom ain m odel. Selain dari propert ies yang didefinisikan pada m odel, kit a m enam bahkan ident ifier propert ies yang akan m em fungsikan unt uk m engident ifikasi keunikan m asing- m asing kej adian obj ek. package jedi.sample.core.bean; public class User { private int userID; private String firstName; private String middleName; private String lastName; private String address; private String emailAdd; private String contactNumber; // getters and setters disini } package jedi.sample.core.bean; 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; public Seminar(SeminarDescription description) { this.description = description; } // getters and setters disini } package jedi.sample.core.bean; public class ClassList { private User[] students; private int seminarID; } package jedi.sample.core.bean; public class Employee { public final static int ADMIN = 1; private int employeeID; private String firstName; private String middleName; private String lastName; private int roleType; // getters and setters disini public boolean isAdmin() { return roleType == Employee.ADMIN; } }
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
Application Interface
Facade Layer Model Data Access LayerDatabase 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.
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 } package jedi.sample.core; public class SeminarFacade { // 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 m engij inkan code client unt uk 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 : ... public boolean addNewUser(User user) { // implementasi untuk saat ini kosong }
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. Mengenai spesifikasi k it a sekarang, im plem ent asi di at as unt uk use case " Add new user" cukup unt uk t uj uan kit a, sedikit nya sej auh lapisan facade t erkait . Sat u- sat unya it em yang dit inggalkan unt uk m elengkapi skenario use case ini adalah unt uk m enyelesaikan im plem ent asi UserDAO dan code unt uk DAOFact ory.
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.
Mendapat kan kem bali inst ance dari Dat aSource t iap kali operasi dat a access adalah t erlalu m ahal : inst ance kit a didapat kan kem bali m enggunakan panggilan JNDI , dan sepert i panggilan biasanya m em punyai asosiasi yang m ahal dengannya. Hal lain unt uk dipert im bangkan adalah kit a hanya akan m em but uhkan sat u inst ance dari Dat aSource unt uk sem ua inst ance dari obj ek dat a access kit a : inst ance ganda t idak dibut uhkan karena sebuah Dat aSource hanya m engenkapsulasi det ail " where- t o- connect " ke dat abase dan t idak m enyediakan koneksinya sendir i. Hal it u m erupakan sebuah obj ek Connect ion yang kit a but uhkan unt uk m em ilik i sebuah inst ance dari m asing- m asing panggilan yang akan kit a buat , bukan sebuah Dat aSource.
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 } }
Dengan m endeklarasikannya sebagai propert i st at is, kit a pst ikan bahwa hanya ada sat u salinan darinya unt uk sem ua inst ance class. Mendapat kannya kem bali di dalam blok st at is m em ast ikan hal it u didapat kan kem bali hanya sekali ( selam a class loading) , dan hal it u siap dan t ersedia kapanpun ket ika beberapa m et hod pada DAO m ungkin akan m em but uhkannya.
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) { return false; } Connection conn; Statement stmt; String sql = "INSERT INTO users VALUES('" + user.getFirstName() + "', '" + user.getMiddleName + "', '" + user.getLastName() + "', '" + user.getAddress + "', '" + user.getEmailAdd + "', '" + user.getContactNumber + "');"; try { conn = ds.getConnection(); stmt = conn.createStatement(); return stmt.executeUpdate() > 1; } catch (SQLException e) { System.err.println("Error occurred while executing user insert query"); e.printStackTrace(); return false; } finally { try { if (stmt != null) { stmt.close(); } } catch (SQLException se) { System.err.println("Error occurred while closing user insert statement"); se.printStackTrace(); } try { if (conn != null) { conn.close(); } } catch (SQLException se) { System.err.println("Error occurred while closing user insert connection"); se.printStackTrace(); } } } ...
I m plem ent asi dari m et hod creat eNewUser adalah langsung, sepert i yang dapat Anda lihat . Pada dasarnya, apa yang dilakukan adalah unt uk m en- generat e st at em ent SQL yang digunakan unt uk m em populasikan dat abase, m endapat kan kem bali inst ance- inst ance dari class- class JDBC yang dibut uhkan, kem udian m engisi SQL ke dalam m et hod execut eUpdat e yang dit em ukan pada obj ek St at em ent .
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. Daripada m enam bahkan m et hod pada obj ek dat a access kit a yang t elah ada sebelum nya, kit a m em buat baru yang dinam akan Sem inarDAO. Pem isahan obj ek dat a access unt uk m asing- m asing set dat a dom ain m em bant u aplikasi k it a m enghindari class yang m em bengkak ( bloat ed) di kem udian. I ni m em bant u pada kem am puan m em baca dan kem am puan m ait enance pada aplikasi kit a.
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. Unt uk m enghindari duplikasi code pada class- class kit a, kit a dapat m engekst rak kem am puan um um it u ke dalam class dasar dim ana class keduanya dapat diperluas . Kit a dapat m enyebut class t ersebut Post greSQLDat aAccessObj ect , im plem ent asinya di baw ah : import javax.naming.*; import javax.sql.DataSource; public class PostgreSQLDataAccessObject { private static DataSource ds = null;
static {
try { Context ctxt = new InitialContext(); ds = (DataSource)ctxt.lookup("jdbc/sampleDataSource"); } catch (NamingException e) { throw new RuntimeException("DataSource cannot be retrieved"); } } public Connection getConnection() throws SQLException{ if (ds == null) return null; return ds.getConnection(); }
public void releaseResources(Connection conn, Statement stmt, ResultSet rs) {
try { if (rs != null) { rs.close(); } } catch (SQLException se) { System.err.println("Error occurred while closing result set"); se.printStackTrace(); // code error handling lain disini } try { if (stmt != null) { stmt.close(); } } catch (SQLException se) { System.err.println("Error occurred while closing statement"); se.printStackTrace(); // code error handling lain disini } try { if (conn != null) { conn.close(); } } catch (SQLException se) { System.err.println("Error occurred while closing connection"); se.printStackTrace(); // code error handling lain disini } } } 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; Statement stmt; String sql = "INSERT INTO users VALUES('" + user.getFirstName() + "', '" + user.getMiddleName + "', '" + user.getLastName() + "', '" + user.getAddress + "', '" + user.getEmailAdd + "', '" + user.getContactNumber + "');"; try { conn = getConnection(); stmt = conn.createStatement(); return stmt.executeUpdate() > 1; } catch (Exception e) { System.err.println("Error occurred while executing user insert query"); e.printStackTrace(); return false; } finally { releaseResources(conn, stmt, null); } } }
1 6 .4 .4 M e n gim ple m e n t a sik a n Se m ina r D AO
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;
String sql = "SELECT * FROM seminars inner join seminardescriptions using(descriptionid)"; Vector seminarList = new Vector(); try { conn = getConnection(); stmt = conn.createStatement(); rs = stmt.executeQuery(sql); while(rs.next()) { SeminarDescription description = new SeminarDescription(); description.setTitle(rs.getString("title")); description.setTopic(rs.getString("topic")); description.setDescription(rs.getString("description")); description.setOutline(rs.getString("outline")); Seminar seminar = new Seminar(description); seminar.setDays(rs.getString("days")); seminar.setTime(rs.getString("time")); seminar.setSeminarID(rs.getInt("seminarid")); seminarList.add(seminar); } return seminarList; } catch (Exception e) { System.err.println("Error occurred while executing user insert query"); e.printStackTrace(); return seminarList; } finally {
releaseResources(conn, stmt, rs);
} } }
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. Obj ek- obj ek ini kem udian dit am bahkan ke dalam inst ance dari int erface Collect ion,dalam hal ini, sebuah Vect or. Class- class yang lain m engim plem ent asikan int erface Collect ion dapat j uga digunakan, sepert i ArrayList at au LinkedList . 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.
I ni m erupakan akhir diskusi kit a pada class- class yang berisikan int i aplikasi. Source code unt uk sisa dari kasus- kasus penggunaan ( use cases) disiapkan dalam bent uk bahan- bahan unt uk m at eri ini.
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 : <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %> <html:errors/> <table> <html:form action="login"> <tr> <td>User Name : </td> <%-- 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>
Halam an ini t idak dapat berfungsi sebagai m ana m est inya. Jika kit a m encoba unt uk m enam pilkan form ini dari suat u web browser ( dengan m enekan Shift - F6) , kit a akan m elew at i perkecualian yang dihasilkan oleh aplikasi. Alasannya adalah deklarasi form kit a: kit a m enet apkan bahw a form ini, ket ika dikirim , dit eruskan dengan act ion pem et aan ke pat h " / login" . Saat ini kit a t idak m em iliki Act ion yang disiapkan unt uk m enangani hal ini, sehingga m enyebabkan error.
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 .
LoginForm dapat dilihat pada halam an selanj ut nya.
a ct ion h a ndle r 1 6 .5 .3 M e m bu a t 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
- Tent ukan nam a class, nam a package, dan act ion pat h unt uk digunakan pada Act ion. Klik Next . ( Unt uk aplikasi kit a, kit a m enggunakan LoginAct ion sebagai nam a class, j edi.sam ple.st rut s.act ion sebagai nam a package, dan / login sebagai act ion pat h) .
• Pilih Act ionForm unt uk digunakan oleh Act ion dari kot ak drop- down. ( Dalam hal ini, kit a
m enggunakan LoginForm
- 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.
Lagi, ket ika m enyim pan obj ek sebagai at ribut di berbagai lingkup yang t ersedia dalm suat u aplikasi w eb ( page, request , session, applicat ion) , sebaiknya m enggunakan St ring const ant s sebagai kunci, dan m em iliki const ant - const ant it u t erlihat dim anapun pada aplikasi. Hal ini m em ast ikan bahwa t idak ada kesalahan ( error) yang t erj adi dalam m endapat kan kem bali obj ek- obj ek t ersebut karena kesalahan cet ak.
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 { LoginForm loginForm = (LoginForm)form; UserFacade facade = new UserFacade(); User user = facade.authenticateUser(loginForm.getUserName(), loginForm.getPassword()); if (user == null) { ActionMessages messages = new ActionMessages(); messages.add("form.error", new ActionMessage("invalid.user.account")); saveMessages(request, messages); return mapping.getInputForward(); } HttpSession session = request.getSession(); 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.
- Mem buat obj ek Act ionForm yang akan m elayani t ransfer form dat a ke act ion handler
- Mem buat obj ek Act ion yang akan di- execut e ket ika form dikirim .
- Mendefinisikan " success" unt uk LoginAct ion yang m enunj ukkan ke layar berikut nya pada aplik
- 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
Menam bahkan definisi Act ionForw ard adalah m udah j ika m enggunakan Net Beans 5's yang m endukung St rut s:
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 == "") { errorMessage += "<bean:message key="errors.password.missing"/>.\n"; } if (errorMessage == "") { return true; } else { alert(errorMessage); return false; } } </script>
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"/> </field> </form> </formset> </form-validation>
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.