diff --git a/2022-11-17-13-00-56.png b/2022-11-17-13-00-56.png new file mode 100644 index 0000000000000000000000000000000000000000..7965980fa96cd60621e19e44e855becd827b51e3 Binary files /dev/null and b/2022-11-17-13-00-56.png differ diff --git a/README.md b/README.md index 7a68d7547f0d300360eaf5a8ce72363c594d788f..f817be7781c1e596eb61d6506d332610866fb0dd 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,64 @@ # Tutorial APAP ## Authors * **Hilmi Al Biruni** - *2006463843* - *APAP-B* +--- +> ### Pertanyaan 1: Apa fungsi dari SSH keys yang Anda buat dengan menggunakan ssh-keygen? Apa perbedaan antara file ~/.ssh/deployer_apap.pub dan ~/.ssh/deployer_apap ? +#### Fungsi dari SSH keys adalah untuk mengakses protokol SSH yang sedang berjalan, seperti username dan password, untuk implementasi SSO oleh administrator. Perbedaan mendasar antara ~/.ssh/deployer_apap.pub dengan ~/.ssh/deployer_apap adalah pada ~/.ssh/deployer_apap.pub dibuat sebagai public key untuk digunakan untuk pembagian server, sedangkan pada ~/.ssh/deployer_apap digunakan untuk private key user masing-masing. + +> ### Pertanyaan 2: Apa perbedaan antara GitLab repository dan GitLab runner? +#### Gitlab repository adalah website open repository untuk menginiasi proyek, lalu pengolahan code, hingga melakukan monitoring security. Sedangkan pada Gitlab runner adalah aplikasi dari Gitlab repository di bagian CI/CD yang digunakan untuk menjalankan pipeline proyek. + +> ### Pertanyaan 3: Apa perbedaan antara Continuous Integration, Continuous Delivery, dan Continuous Deployment? +- Continuous Integration adalah proses automasi build dan test software setiap push ke repositori +- Continuous Delivery adalah proses lanjutan dari Continous Integration di mana terjadi proses automasi lanjutan dalam men-deploy semua code yang berubah menjadi testing dan/atau production environment setelah build stage +- Continuous Deployment adalah proses lanjutan dari Continous Delivery yaitu setiap perubahan yang telah melewati semua stage dalam pipeline kita akan sepenuhnya dirilis kepada pengguna dan sistem akan memegang kendali ini semua sampai proses ini selesai, kecuali ada error yang terjadi +> ### Pertanyaan 4: Apa perbedaan dari stages-stages yang berada dalam file .gitlab-ci.yml? +- Pada stage build, dilakukan compiling code yang akan di build dalam file jar seperti .gradlew pada terminal local. +- Pada stage test, dilakukan unit testing saat build project untuk melihat apakah terdapat error pada code di project tersebut. +- Pada stage build-image, dilakukan build image menggunakan docker yang akan berkontakan dengan variabel REGISTRY_SERVER masing-masing pengguna. +- Pada stage publish-image, dilakukan pengunggahan hasil build image tersebut ke REGISTRY_SERVER masing-masing pengguna. +- Terakhir, pada stage deploy, dilakukan penyettingan ssh dengan command linux, lalu menggunakan informasi pada docker-compose-deploy.yml untuk menghubungkan ke DEPLOY_USERNAME dan DEPLOY_SERVER masing-masing pengguna. +> ### Pertanyaan 5: Pada script gitlab-ci.yml, terdapat perubahan if: $CI_COMMIT_BRANCH == 'main' menjadi if: $CI_COMMIT_BRANCH == 'feat/tutorial-9-belajarbelajar'. Apa fungsi dari perubahan tersebut? +#### Fungsi dari perubahan tersebut untuk menggunakan path branch yang benar untuk commit karena default untuk pengerjaan tutorial ini berada di feat/tutorial-9-belajarbelajar + +> ### Pertanyaan 6: Apa yang dimaksud dengan "docker registry"? Apa fungsinya? +#### Docker registry adalah sistem registry yang digunakan untuk menyimpan dan mendistribusikan docker images. Hal tersebut berfungsi agar registry akan menerimanya dan menyimpan image tersebut ketika pengguna Docker mengambil image secara lokal dan meng-overwrite image baru + +> ### Pertanyaan 7: Dalam gitlab CI/CD, apa perbedaan antara: pipeline, stage, dan job? +- Pipeline merupakan wadah dari stage dan jobs di mana setiap kali kita melakukan push. Pipeline akan mengeksekusi semua stage dan jobs dalam urutan yang tepat dan konfigurasinya terdapat dalam .gitlab-ci.yml. +- Stage adalah tahap-tahap yang akan dilewati suatu job yaitu build-test-deploy yang mana tahap tersebut bekerja secara seri yaitu stage berikutnya tidak akan bekerja sebelum stage sebelumnya selesai dan hal tersebut bisa diatur ulang dalam .gitlab-ci.yml. +- Jobs adalah perintah untuk menjalankan suatu task mungkin itu menjalankan testint , melakukan quality check, atau mencoba melihat coverage suatu kode, dan lain sebagainya. +> ### Pertanyaan 8: Sertakan screenshot fullscreen saat Anda mengakses apap-xxx.cs.ui.ac.id ketika sudah berhasil men-deploy aplikasi menggunakan CI/CD! + +> ### Pertanyaan 9: Kapan proses CI/CD dijalankan di GitLab? +#### Proses ini dilakukan setelah kita melakukan commit push pada proyek repository. +> ### Pertanyaan 10: Mengapa CI/CD ini penting? Apa manfaatnya? +#### CI/CD penting digunakan karena proses pengiriman kode aplikasi ke server deploy dapat ter-automasi melewati stages dan job pipeline. Dengan CI/CD, kita bisa meminimalisir kesalahan dan dapat dilakukan monitoring dan controlling pada kode aplikasi yang di commit push ke repository + --- ## Tutorial 8 -### Pertanyaan 1: Apa itu Dockerfile dan docker-compose.yaml? Apa fungsinya? +> ### Pertanyaan 1: Apa itu Dockerfile dan docker-compose.yaml? Apa fungsinya? #### Dockerfile adalah file environment agar dapat menggunakan Docker pada proyek springboot tersebut. #### Sedangkan docker-compose.yaml adalah alat untuk mendefinisikan dan menjalankan satu atau lebih container yang saling terkait pada sebuah command -### Pertanyaan 2: Screenshot hasil perubahan anda. Setelah anda menyelesaikan tutorial ini, menurut anda, mengapa kita perlu mengganti port? +>### Pertanyaan 2: Screenshot hasil perubahan anda. Setelah anda menyelesaikan tutorial ini, menurut anda, mengapa kita perlu mengganti port?  #### Perubahan port pada docker-compose.yml dilakukan agar kita bisa menggunakan cabang port dari 8080, yaitu 10127. Hal ini untuk mengurangi traffic dengan aplikasi yang menggunakan port serupa. -### Pertanyaan 3: Mengapa terdapat versi dev dan prod? File apa yang menentukan konfigurasi mana yang dipakai? Apa yang harus dilakukan untuk menjalankan versi prod? (hint: baca file pada langkah 3 dengan teliti) +> ### Pertanyaan 3: Mengapa terdapat versi dev dan prod? File apa yang menentukan konfigurasi mana yang dipakai? Apa yang harus dilakukan untuk menjalankan versi prod? (hint: baca file pada langkah 3 dengan teliti) #### application-dev.yml berfokus digunakan untuk tahap development dan productivity, sedangkan application-prod.yml berfokus digunakan untuk tahap performance dan scalability. application-prod.yml juga digunakan untuk menentukan konfigurasi yang dipakai karena didalamnya didefinisikan suatu port tertentu, yaitu 8080 untuk prod dan 2020 untuk prod2. #### Dalam menggunakan versi prod, kita memanggilnya pada app.env di bagian *SPRING_PROFILES_ACTIVE*. Lalu, pada docker-compose.yml akan memanggil app.env pada *env_file:*. Dari docker-compose.yml akan digunakan oleh Dockerfile sehingga application-prod.yml berhasil digunakan. -### Pertanyaan 4: Apa saja yang terjadi di langkah ini? +>### Pertanyaan 4: Apa saja yang terjadi di langkah ini? #### Saya berpindah ke directory belajarbelajar, lalu melakukan build jar agar menggunakan build versi terbaru, kemudian melakukan build image dengan *docker-compose up*. Command tersebut berfungsi untuk membangun, membuat, memulai, dan melampirkan container untuk service. Secara tidak langsung, container akan dibuat dan langsung dijalankan tanpa tambahan command lainnya -### Pertanyaan 5: Sertakan screenshot container yang sedang berjalan (versi gui atau cli, pilih salah satu). Apa itu docker container, images, dan volume? +> ### Pertanyaan 5: Sertakan screenshot container yang sedang berjalan (versi gui atau cli, pilih salah satu). Apa itu docker container, images, dan volume?  @@ -32,20 +66,20 @@ #### Docker images adalah sebuah file yang digunakan untuk mengeksekusi kode pada docker container #### Docker volume adalah sebuah file untuk menyimpan data pada aplikasi dari docker container -### Pertanyaan 6: Apa perbedaan docker-compose down dan stop? +>### Pertanyaan 6: Apa perbedaan docker-compose down dan stop? #### *docker-compose down* berfungsi untuk memberhentikan container sekaligus menghapus container, sehingga perlu dilakukan *docker-compose build*. #### *docker-compose stop* berfungsi hanya untuk memberhentikan container tanpa menghapus container. -### Pertanyaan 7: Sertakan screenshot mengakses laman kirti milik anda melalui browser (seperti screenshot di atas) +>### Pertanyaan 7: Sertakan screenshot mengakses laman kirti milik anda melalui browser (seperti screenshot di atas)  -### Pertanyaan 8: Ceritakan pengalaman anda melakukan deployment ke Kirti. Kendala apa yang anda alami? +>### Pertanyaan 8: Ceritakan pengalaman anda melakukan deployment ke Kirti. Kendala apa yang anda alami? #### Hasil dari deployment menggunakan Kirti menurut saya cukup menyenangkan karena kita bisa melihat hasil nyata aplikasi lewat link, yaitu apap-127 dengan domain cs.ui.ac.id. Kendala yang saya alami adalah server kawung sering overload sehingga saya selalu overtime saat melakukan build dan deployment. Contoh spesifiknya adalah saat melakukan upload frontend dan backend, hanya frontend saya yang terupload di kawung, sedangkan backend tidak. -### Pertanyaan 9: Buka container docker Anda, lalu screenshot. Apa perbedaan tampilan container sekarang dengan tampilan container pada langkah tutorial docker di awal tadi? +>### Pertanyaan 9: Buka container docker Anda, lalu screenshot. Apa perbedaan tampilan container sekarang dengan tampilan container pada langkah tutorial docker di awal tadi? *maaf, saya tidak sempat menyertakan screenshoot di awal tahap docker*  @@ -53,19 +87,19 @@ #### Perbedaannya adalah pada tahap awal docker, hanya terdiri dari tutorial-apap, db-1, dan web-1. Sedangkan di tahap sekarang, bertambah menjadi tutorial-apap, db-1, web2-1, web-1. #### Hal ini dikarenakan pada tahap ini saya membuat 2 port sehingga membutuhkan 2 container, yaitu web2-1 dan web-1. -### Pertanyaan 10: Sertakan screenshot tampilan web ketika pertama kali menjalankan localhost:9090 dan tampilan web ketika halaman di-refresh. +>### Pertanyaan 10: Sertakan screenshot tampilan web ketika pertama kali menjalankan localhost:9090 dan tampilan web ketika halaman di-refresh. #### Port 8080 sebelum melakukan refresh  #### Port 2020 setelag melakukan refresh  -### Pertanyaan 11: Kendala apa yang anda hadapi ketika melakukan tutorial bagian nginx? +>### Pertanyaan 11: Kendala apa yang anda hadapi ketika melakukan tutorial bagian nginx? #### Kendala saya adalah ketidaktelitian saya saat melakukan configurasi pada docker-compose.yml. Selain itu, tidak ada kendala lain. - +--- ## Tutorial 7 -### Pertanyaan 1: Jelaskan secara singkat perbedaan Otentikasi dan Otorisasi! Di bagian mana (dalam kode yang telah anda buat) konsep tersebut diimplementasi? +>### Pertanyaan 1: Jelaskan secara singkat perbedaan Otentikasi dan Otorisasi! Di bagian mana (dalam kode yang telah anda buat) konsep tersebut diimplementasi? #### Otentikasi adalah proses melakukan verifikasi apakah pengguna yang ingin melakukan login dengan username yang dimiliki terlah tersedia di database dan dapat masuk untuk mengakses aplikasi. Sedangkan, otorisasi adalah proses untuk menentukan hak pengguna apakah pengguna tersebut memiliki akses ke halaman tertentu yang telah ditentukan otentifikasinya. @@ -93,29 +127,29 @@ http .logoutSuccessUrl("/login").permitAll(); ``` -### Pertanyaan 2: Apa itu BCryptPasswordEncoder? Jelaskan secara singkat cara kerja dan tujuannya. +>### Pertanyaan 2: Apa itu BCryptPasswordEncoder? Jelaskan secara singkat cara kerja dan tujuannya. #### BCryptPasswordEncoder merupakan sebuah class yang mengimplementasikan PasswordEncoder dan juga menyediakan password hashing. Untuk melakukan register password, tidak mungkin dengan menggunakan plaintext, maka penyimpanan password menggunakan hashing. BCryptPasswordEncoder bekerja dengan menyimpan password yang telah di-hashing terlebih dahulu. -### Pertanyaan 3: Apakah penyimpanan password sebaiknya menggunakan encryption atau hashing? Mengapa demikian? +>### Pertanyaan 3: Apakah penyimpanan password sebaiknya menggunakan encryption atau hashing? Mengapa demikian? #### Encryption dan hashing merupakan dua istilah yang berbeda. Encryption adalah proses mengubah sebuah pesan normal (plaintext) menjadi pesan yang tidak mudah dibaca (ciphertext). Ciphertext yang diperoleh dari encryption dapat dengan mudah diubah menjadi plaintext menggunakan encryption key. Hashing adalah proses mengubah informasi menjadi kunci menggunakan hash function. Informasi asli tidak dapat diambil dari hash key dengan cara apapun. Dengan demikian, penyimpanan password akan lebih aman jika dilakukan dengan hashing daripada encryption. -### Pertanyaan 4: Jelaskan secara singkat apa itu UUID beserta penggunaannya! +>### Pertanyaan 4: Jelaskan secara singkat apa itu UUID beserta penggunaannya! #### UUID (Universally Unique Identifier) merupakan kode dengan jumlah hashing terbanyak yaitu sebanyak 32 karakter yang akan digunakan untuk keamanan data. UUID di-generate untuk id pengguna. Dibandingkan dengan BCrypt yang merupakan password yang berguna untuk mengamankan id dari hacking. Dapat dipastikan UUID yang tergenerate unik untuk tiap objek yang ada di internet, jadi id yang dimiliki pengguna akan aman. -### Pertanyaan 5: Apa kegunaan class UserDetailsServiceImpl.java? Mengapa harus ada class tersebut? +>### Pertanyaan 5: Apa kegunaan class UserDetailsServiceImpl.java? Mengapa harus ada class tersebut? #### Class UserDetailsServiceImpl.java memberikan informasi mengenai Otentikasi dan Otorisasi akun yang ada pada class lain. Class ini harus diimplementasikan, jika tidak informasi tersebut tidak dapat diberikan. Kemampuan tersebut ada karena class mengimplementasikan UserDetailService. UserDetailService merupakan interface yang ada dari Spring Security. Selain itu, class ini meng-override loadUserByUsername() yang bisa dilakukan kustomisasi untuk pencarian user. --- ## Tutorial 6 -### Pertanyaan 1: Perhatikan apa yang terjadi pada file index.html pada branch feat/tutorial-6-advancedgit-1. Apa yang terjadi setelah git cherry-pick dilakukan? Apakah kita bisa melakukan cherrypick tanpa harus melakukan commit? +>### Pertanyaan 1: Perhatikan apa yang terjadi pada file index.html pada branch feat/tutorial-6-advancedgit-1. Apa yang terjadi setelah git cherry-pick dilakukan? Apakah kita bisa melakukan cherrypick tanpa harus melakukan commit? #### File index.html dipull dari branch tut6-for-cherrypick sehingga index.html ada pada branch feat/tutorial-6-advancedgit-1. Git cherry pick mencari commit-id yang akan mengambil file dari branch tertentu. Dalam melakukan hal itu, perlu dilakuka commit agar dapat terdefinisi commit-id -### Pertanyaan 2: Conflict ini terjadi karena pada branch feat/tutorial-6-advancedgit-1 sudah ada kode dengan baris yang sama di index.html dengan branch tut6-for-merge sehingga akan menimbulkan collisons jika dilakukan merging. +>### Pertanyaan 2: Conflict ini terjadi karena pada branch feat/tutorial-6-advancedgit-1 sudah ada kode dengan baris yang sama di index.html dengan branch tut6-for-merge sehingga akan menimbulkan collisons jika dilakukan merging. -### Pertanyaan 3: Apa yang terjadi pada log history setelah melakukan rebase (branch rebase-1 dan rebase-2)? Sertakan screenshot log history anda pada kedua branch tersebut! +>### Pertanyaan 3: Apa yang terjadi pada log history setelah melakukan rebase (branch rebase-1 dan rebase-2)? Sertakan screenshot log history anda pada kedua branch tersebut! #### Log histori pada rebase-1 terdapat juga pada log histori rebase-2. @@ -125,68 +159,70 @@ http #### Maka akan terdapat juga pada branch rebase-2  -### Pertanyaan 4: Jelaskan perbedaan dari "rebase –continue", "rebase –skip", dan "rebase –abort"! +>### Pertanyaan 4: Jelaskan perbedaan dari "rebase –continue", "rebase –skip", dan "rebase –abort"! #### Pada "rebase --continue" akan melaksanakan rebase suatu pada perintah jika konflik sudah disolve. Lalu, pada "rebase --skip" akan mengabaikan bagian yang terkena konflik. Kemudian, pada "rebase --abort" akan membatalkan proses rebase. -### Pertanyaan 5: Jelaskan perbedaan git rebase dan git merge! +>### Pertanyaan 5: Jelaskan perbedaan git rebase dan git merge! #### Pada git rebase melakukan penggabungan urutan commit pada suatu branch ke urutan commit pada branch yang dituju. Sebagai contoh, kita mengerjakan kode pada branch B dan melakukan commit disana. Kita dapat memindahkan urutan commit branch B ke urutan branch A tanpa mengubah kode pada branch A. Hal ini digunakan jikalau saat mengerjakan branch A kita membutuhkan sesuatu pada branch B, maka kita tinggal melakukan pull commit-id pada branch A yang terdapat juga di branch B. ### Berbeda dengan git merge yang melakukan merge kode dari branch B dengan branch A sehingga kode/file pada branch A akan berubah -### Pertanyaan 6: Pada tahap ini apakah yang terjadi pada direktori git-stash? +>### Pertanyaan 6: Pada tahap ini apakah yang terjadi pada direktori git-stash? #### Pada git-stash akan tersimpan didalam local repository Git dan harus melakukan git stash pop untuk mengakses direktori -### Pertanyaan 7: Apa yang terjadi pada file abc.txt setelah melakukan git reset --hard? Bagaimana kondisi lognya? Apa perbedaan git reset dengan git revert? +>### Pertanyaan 7: Apa yang terjadi pada file abc.txt setelah melakukan git reset --hard? Bagaimana kondisi lognya? Apa perbedaan git reset dengan git revert? #### git reset akan mereset file abc.txt ke versi sebelumnya, yang berisi string "this is first line from abc file". Kondisi lognya pun akan hilang. #### Lalu, perbedaan git reset dengan git revert adalah git reset dapat mengembalikan ke versi direktori tertentu. Sedangkan git revert hanya dapat mengembalikan ke versi direktori sebelumnya. Jadi, secara teknis, git reset dapat mengembalikan versi direktori sesuai yang kita mau. --- ## Tutorial 5 -### Pertanyaan 1: Apa itu Postman? Apa kegunaannya? +>### Pertanyaan 1: Apa itu Postman? Apa kegunaannya? #### Postman adalah sebuah developent tool API yang digunakan untuk build, modify, dan test API. Penggunaan Postman dapat digunakan untuk mendesign, mock, debug, tes, dokumentasi, monitor, dan juga menerbitkan API. Postman memiliki fungsi REST Client yang dapat digunakan untuk menguji REST API. -### Pertanyaan 2: Jelaskan fungsi dari anotasi @JsonIgnoreProperties dan @JsonProperty +>### Pertanyaan 2: Jelaskan fungsi dari anotasi @JsonIgnoreProperties dan @JsonProperty #### @JsonIgnoreProperties digunnakan untuk memberikan spesifikasi list atribut dari sebuah class yang diabaikan saat menjalankan serialization dan deserialozation JSON. Jika #### @JsonIgnoreProperties tidak disertakan, nantinya akan menyebabkan error saat menjalankan serialization dan deserialization saat Java Object tidak memiliki field yang ada pada JSON. -### Pertanyaan 3: Apa kegunaan atribut WebClient? +>### Pertanyaan 3: Apa kegunaan atribut WebClient? #### Kegunaan dari Webclient adalah untuk menghubungkan personal komputer ke jaringan internet yang meminta informasi. Dalam mengakses webserver diperlukan sebuah WebClient untuk menggunakan aplikasi yaitu WebBrowser. -### Pertanyaan 4: Apa itu ResponseEntity dan BindingResult? Apa kegunaannya? +>### Pertanyaan 4: Apa itu ResponseEntity dan BindingResult? Apa kegunaannya? #### ResponseEntity merupakan representasi keluruhan HTTP Response dari status code, header, dan body. Dengan demikian, dapat digunakan untuk mengkonfigurasi secara lengkap HTTP response. BindingResult adalah sebuah objek spring yang akan menyimpan hasil validasi, binding, dan error dari model objek yang divalidasikan. Penggunaan BindingResult diletakkan setelah parameter objek divalidasi. --- ## Tutorial 4 -### Pertanyaan 1: Jelaskan perbedaan th:include dan th:replace! +>### Pertanyaan 1: Jelaskan perbedaan th:include dan th:replace! #### Perbedaan dari include dan replace adalah penempatan suatu konten dari fragment #### Include akan memanggil isi dari fragment ke dalam th:include tersebut. Lalu, include akan memasukkan konten fragment tanpa menyisipkan tag fragment itu sendiri. #### Berbeda dengan include, replace menerapkan konsep parent-kid dalam pengimplementasian fragment tersebut. Replace akan memasukkan konten dari fragment dengan mengganti tag menjadi tag yang mendefinisikan fragment sehingga dapat di kustomisasi. -### Pertanyaan 2: Jelaskan apa fungsi dari th:object! +>### Pertanyaan 2: Jelaskan apa fungsi dari th:object! #### th:object digunakan untuk menyederhanakan pemanggilan suatu objek di dalam HTML. th:object akan menggunakan atribut langsung dari objek tanpa harus menspesifikasikan objek yang dipanggil. -### Pertanyaan 3: Jelaskan perbedaan dari * dan $ pada saat penggunaan th:object! Kapan harus dipakai? +>### Pertanyaan 3: Jelaskan perbedaan dari * dan $ pada saat penggunaan th:object! Kapan harus dipakai? #### * digunakan untuk menyatakan sebuah selection dan menunjuk kepada atribut darri suatu objek. Berbeda dengan $ yang digunakan untuk menyatakan sebuah variabel/value dan menunjuk kepada atribut suatu objek. -### Pertanyaan 4: Bagaimana parameter/params tersebut bekerja sehingga Anda dapat menambahkan 1 baris penyelenggara pada form tambah course? +>### Pertanyaan 4: Bagaimana parameter/params tersebut bekerja sehingga Anda dapat menambahkan 1 baris penyelenggara pada form tambah course? #### params perlu dibuat terlebih dahulu logic-nya dalam struktur data List. params akan mendefinisikan semacam "function" agar dapat diimplementasikan di dalam <button> dalam variable "name". -### Pertanyaan 5: Bagaimana parameter/params tersebut bekerja sehingga Anda dapat menghapus 1 baris penyelenggara pada form tambah course? +>### Pertanyaan 5: Bagaimana parameter/params tersebut bekerja sehingga Anda dapat menghapus 1 baris penyelenggara pada form tambah course? #### params perlu dibuat terlebih dahulu logic-nya sebagai berikut: -##### final Integer rowId = Integer.valueOf(row); -##### course.getListPengajar().remove(rowId.intValue()); +``` +final Integer rowId = Integer.valueOf(row); +course.getListPengajar().remove(rowId.intValue()); +``` #### Nanti params tersebut akan mendefinisikan semacam "function" agar dapat diimplementasikan di dalam <button> dalam variable "name". - +--- ## Tutorial 3 ### Pertanyaan 1: Tolong jelaskan secara singkat apa kegunaan dari anotasi-anotasi yang ada pada model (@AllArgsConstructor, @NoArgsConstructor, @Setter, @Getter, @Entity, @Table)