Thursday, March 22, 2012

Spring Web Application part 1: Dynamic Url Mapping

Sekedar berbagi dan dokumentasi ilmu, siapa tau suatu saat nanti saya lupa ketika harus membuat aplikasi web dengan spring seperti ini. Tutorial ini rencananya merupakan seri pertama dari beberapa tutorial berikutnya. Rencananya saya akan membuat tutorial yang berkelanjutan, hal-hal yang akan dibahas adalah sebagai berikut:

  1. Membangun aplikasi web menggunakan Spring dengan memanfaatkan anotasi dan dynamic route (Akan dibahas pada tutorial kali ini).
  2. Memanfaatkan apache tiles untuk membuat template secara dinamis.
  3. Memanfaatkan spring security untuk mengatur session
  4. Menggunakan hibernate untuk akses database.


Requirement:
  1. Java 6 atau yang lebih baru
  2. Apache Tomcat 7 atau yang lebih baru
  3. NetBeans 7  atau yang lebih baru dengan plugin JavaEE
  4. File aopalliance-1.0.jar.
Mari kita mulai, pertama-tama, buat project baru di NetBeans.

Jenis project yang akan dibangun adalah Web Application. Jenis project ini terdapat dalam kategori JavaWeb. Jika anda tidak menemukan kategori JavaWeb, silahkan install plugin JavaWeb terlebih dahulu.

Nama project yang akan saya gunakan sebagai contoh adalah SpringWebApp. Untuk opsi lain, silahkan sesuaikan dengan gambar di bawah ini

Pada step Server and Settings, pilih apache tomcat yang sudah teregistrasi pada NetBeans. Jika server tomcat belum terintegrasi dengan NetBeans, silahkan registrasikan server tomcat anda terlebih dahulu.

Pada step Frameworks, tidak perlu melakukan apa-apa, langsung saja klik Finish. Kemudian kita akan melihat project yang telah kita buat pada jendela Projects.
Untuk setup awal, kita akan melakukan konfigurasi folder library. Hal ini untuk memudahkan ketika kita ingin membuka project ini pada mesin lain. klik kanan pada nama project, kemudian pilih Properties. Pada dialog Project Properties, pilih kategori Libraries. Kemudian pada isian Libraries Folder, klik tombol Browse.


Pada dialog Select Libraries Folder, pilih folder web/WEB-INF/lib sebagai folder library. Untuk lebih jelasnya bisa dilihat pada gambar berikut.



Jika folder library sudah dikonfigurasu, kita akan menambahkan library yang akan dibutuhkan oleh aplikasi yang akan dibangun. Pada tab compile, klik tombol Add Library...

Kemudian pada dialog Add Library, klik tombol import. Hal ini dilakukan untuk melakukan import library yang sudah terdapat pada NetBeans agar tersedia untuk project yang akan kita bangun.

Pada dialog Import Library, pilih library JSTL 1.1, Log4J, Spring Framework 3.0.6.RELEASE, nomor versi mungkin tidak sama, tergantung versi NetBeans yang digunakan. Pada saat membuat tutorial ini, saya menggunakan NetBeans 7.1. Setelah ketiga library tadi kita import, kita akan kembali ke dialog Add Library dengan tambahan tiga library baru yang tersedia untuk kita masukkan ke dalam aplikasi kita. Pilih ketiga library tersebut, kemudian klik Add Library. Untuk lebih jelasnya bisa dilihat pada gambar berikut.

Kemudian kita akan memerlukan file aopalliance-1.0.jar (link download disediakan di bagian requirement) untuk dimasukkan ke dalam daftar library.
Masih pada bagian Libraries, klik Add JAR/Folder.



Pilih file aopalliance-1.0.jar yang sudah didownload, untuk opsional yang lain dapat disesuaikan dengan gambar di bawah ini.



 Step ini adalah opsional, jika kita tidak ingin NetBeans melakukan kompilasi otomatis setiap kita melakukan save file.
 Begitu juga step ini hanya opsional, jika kita tidak ingin NetBeans melakukan deploy secara otomatis ketika kita melakukan save.

Berikut ini adalah struktur direktori yang siap akan kita gunakan. Pada gambar di bawah, terdapat file index.jsp dan file beans.xml. Kedua file ini tidak kita butuhkan, jadi aman untuk dihapus.

Setelah persiapan project sudah siap, kita akan memulai membuat konfigurasi spring. Konfigurasi untuk spring, dimulai dari file /WEB-INF/web.xml. Untuk jelasnya, bisa dilihat pada gambar berikut.



Berikut ini merupakan isi dari web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/applicationContext.xml
        </param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
     <!-- Handles all requests into the application -->
    <servlet>
        <servlet-name>main</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>main</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

Kemudian kita perlu membuat file applicationContext.xml, untuk lebih jelasnya bisa dilihat pada gambar di bawah ini.
Berikut ini isi file application.Context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context 
                           http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <context:annotation-config />
    <context:component-scan base-package="com.springwebapp" />

    <!-- Imports the configurations of the different infrastructure systems of the application -->
    <import resource="webmvc-context.xml" />
    

</beans>

Pada application context, terdapat 2 kunci untuk menunjang keberhasilan penggunaan anotasi.



Kedua baris tersebut akan melakukan scanning anotasi @Controller pada package "com.springwebapp". Untuk lebih jelasnya, nanti kita akan bahas lebih detail.

Kemudian applicationContext.xml akan me-load webmvc-context.xml.
Kenapa banyak sekali file yang harus diload? Ya, saya sengaja memisahkan beberapa bagian xml agar lebih mudah proses maintenancenya. webmvc-context.xml akan menyimpan konfigurasi yang berkaitan dengan proses MVC. Sedangkan nanti akan ada lagi xml untuk menyimpan konfigurasi koneksi database, tapi itu belum akan kita bahas saat ini. :)
Berikut ini adalah isi file webmvc-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context 
                           http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/mvc
                           http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <mvc:annotation-driven />
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>    
    
    <bean id="viewResolver" 
    class="org.springframework.web.servlet.view.ResourceBundleViewResolver" 
    p:basename="views" />
    <!-- Declare the Interceptor -->
    <mvc:interceptors>    
        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"
              p:paramName="locale" />
    </mvc:interceptors>
    
    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources/ directory -->
    <mvc:resources mapping="/resources/**" location="/resources/" />
    
    <!-- Declare the Resolver -->
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver" />
    
    <!-- Application Message Bundle -->
    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="/WEB-INF/messages/messages" />
        <property name="cacheSeconds" value="0" />
    </bean>
    
</beans>

Sekarang konfigurasi framework sudah selesai disiapkan. Saatnya mulai coding ke Java dan JSP. :)
Pada framework ini, kita akan menggunakan konsep MVC, dimana terdapat Controller yang bertugas menangani proses-proses transaksional, dan View yang bertugas menampilkan data-data yang dihasilkan oleh controller.
Kita mulai dengan membuat controller.
Seperti yang didefinisikan pada applicationContext.xml, Spring akan melakukan scanning anotasi pada package com.springwebapp, maka kita perlu membuat package bernama com.springwebapp. Kemudian untuk mempermudah proses maintenance, semua controller akan diletakkan pada package com.springwebapp.controller. 
Untuk membuat package-package yang diperlukan, prosesnya digambarkan pada gambar di bawah ini.


Setelah package com.springwebapp.controller dibuat, kita mencoba membuat controller pertama, pada contoh ini saya namakan MainController.java.



Berikut ini adalah isi dari MainController.java

package com.springwebapp.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

/**
 *
 * @author angga
 */
@Controller
@RequestMapping(value = "/")
public class MainController {

    @RequestMapping(value = "")
    public ModelAndView index() {
        ModelAndView mv = new ModelAndView("index");
        return mv;
    }
}

kata kunci yang membedakan controller dengan class-class lain adalah terdapatnya anotasi @Controller. Dengan adanya anotasi ini, maka class ini akan memiliki behaviour sebgai controller. Kemudian terdapat juga anotasi @RequestMapping. Anotasi ini berfungsi melakukan pemetaan url dengan controller yang bersangkutan. Kita lihat syntax berikut:
@RequestMapping(value = "/")
Anotasi ini akan memetakan url root "/" dengan controller MainController. Kemudian pada method index(), terdapat anotasi lagi dengan value berupa String kosong. Maka, jika kita memasukkan url http://:/, Spring akan mengeksekusi method ini.
Kemudian pada MainController, kita akan menemukan syntax sebagai berikut:
ModelAndView mv = new ModelAndView("index");
return mv;

Syntax tersebut mendefinisikan view mana yang akan diload jika method tersebut dieksekusi. Dalam contoh ini adalah "index".

Sebelumnya, mari kita lihat kembali webmvc-context.xml. Kita akan menemukan entry sebagai berikut:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

Xml tersebut mendefinisikan view yang harus di-load. Dalam hal ini view akan ditambahkan prefix "/WEB-INF/jsp/" dan suffix ".jsp". Maka, view "index" untuk method index() pada MainController harus diletakkan pada /WEB-IND/jsp/index.jsp.
Untuk lebih jelasnya, kita lihat gambar di bawah ini untuk proses membuat view.




Berikut ini adalah isi file index.jsp.

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Spring MVC Web Application</title>
    </head>
    <body>
<h1>Home</h1>
<div>
    This is a Spring MVC Web Application.
    <br/>
    This is Home index view.
</div>
    </body>
</html>

Sekarang Aplikasi sudah siap untuk dicoba. Namun sebelumnya, untuk memudahkan tracing jika terjadi kesalahan, ada baiknya kita melakukan setup log4j untuk keperluan logging.
Langkah ini adalah opsional. Berikut gambaran cara setup log4j.

Buat file log4j.properties pada folder src/java.

Berikut ini adalah contoh sederhana isi file log4j.properties.
log4j.rootCategory=DEBUG, S

log4j.appender.S = org.apache.log4j.ConsoleAppender
log4j.appender.S.layout = org.apache.log4j.PatternLayout
log4j.appender.S.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n

Kemudian kita siap untuk mengeksekusi aplikasi kita. Pertama kita harus compile source code yang kita buat. Salah satu caranya adalah dengan klik kanan pada nama project, kemudian pilih Build atau Clean and Build

Kemudian, jika proses compile sudah selesai tanpa ada pesan error, klik kanan sekali lagi pada nama project, dan pilih Deploy untuk melakukan proses deploy aplikasi ke server. Proses ini membutuhkan server tomcat yang berjalan, jika server tomcat belum berjalan, maka server tomcat akan dijalankan otomatis oleh NetBeans.

Jika proses deploy sudah berhasil tanpa ada pesan error, kita dapat melihat hasilnya pada browser, dengan mengetikkan alamat http://:/SpringWebApp/. Pada system saya, server tomcat berjalan pada port 8090, maka saya menggunakan alamat http://localhost:8090/SpringWebApp/ pada browser saya. Berikut ini adalah hasilnya.

Untuk latihan, mari kita membuat satu controller lagi, misalnya HomeController, kemudian view indexnya akan diletakkan pada /WEB-INF/jsp/home/index.jsp.
Jika berhasil, hasilnya akan tampak mirip dengan gambat di bawah ini.


Demikian untuk kali ini. Jika ada yang berminat untuk melihat source code yang saya buat, bisa coba dicek ke https://bitbucket.org/anggabastian/springwebapp.
Berikutnya, kita akan mencoba template engine yang disebut dengan Tiles2. :)




1 comment:

  1. permisi gan, saya ada sedikit tulisan mengenai protokol websocket di java berikut gan: http://datacomlink.blogspot.co.id/2015/11/script-java-websocket-rfc-6455-server.html ditunggu feedback-nya ya gan, semoga menambah wawasan bersama.. terima kasih gan..

    ReplyDelete