23 January 2016

Memulai spring-boot

Salam jumpa, wahai pembaca semua, kali ini sudah benar-benar sangat lama saya baru bisa menulis kembali di blog saya ini. Kali ini saya tidak akan beralasan macam-macam lagi kenapa saya jarang sekali menulis. Saya hanya memang tidak sempat menulis karena memang tidak memiliki bahan yang bisa saya kategorikan menarik untuk di bagikan (share).
Pindah kerja saya juga menjadi satu alasan yang paling tepat bagi saya untuk bisa menjelaskan kenapa baru sekarang ini saya memiliki kesempatan untuk bisa lagi menulis buat blog saya tercinta ini. Ah sudahlah, mari kita langsung kembali ke inti tema tutorial kali ini.
Kali ini kita akan mencoba mengimplementasikan salah satu varian terbaru dari springframework, yaitu spring-boot. Spring-boot adalah sebuah framework yang merupakan kompilasi dari beberapa elemen library spring framework. Spring-boot diciptakan dengan tujuan untuk memudahkan para pengguna spring framework agar dapat :


  1. Mudah membuat aplikasi berbasiskan spring framework.
  2. Kontainer web aplikasi seperti tomcat, jetty atau undertow sudah terintegrasi di dalamnya.
  3. Menyediakan sebuah skema 'tinggal pakai' untuk menyederhanakan developer jika menggunakan maven dalam proses development-nya.
  4. Memungkinkan pengkonfigurasian spring framework semudah mungkin.
  5. Menyediakan fitur-fitur yang siap pakai pada saat produksi, seperti metrics, health checks, dan konfigurasi yang bisa ditempatkan diluar aplikasi.
  6. Tidak menggunakan xml sebagai konfigurasi spring-nya.

Wow, dari fitur-fitur tersebut, sepertinya spring-boot ini sangat menarik untuk dicoba bukan ?. Mari kita coba, langkah pertama yang kita lakukan adalah setup project tentunya, silahkan ikuti langkah langkah berikut ini:
Buat sebuah folder dengan nama spring-boot-learn dimana saja terserah anda, yang pasti folder ini adalah folder project tutorial kita, dan pastinya project ini bernama spring-boot-learn. Dalam folder spring-boot-learn tersebut, buat beberapa direktori dengan struktur berikut ini:
Kemudian buatlah sebuah file pom.xml dalam folder spring-boot-learn tersebut, adapun isi dari file pom.xml tersebut seperti berikut ini:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.josescalia</groupId>
    <artifactId>spring-boot-learn</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>1.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>1.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>1.2.2.RELEASE</version>
            <scope>test</scope>
        </dependency>

        <!--mysql-driver-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.30</version>
        </dependency>
    </dependencies>

</project>
Seperti yang kita lihat dalam file pom.xml tersebut, kita menggunakan library spring-boot-starter, spring-boot-starter-data-jpa, dan spring-boot-starter-test, library lain yang kita gunakan adalah driver-mysql, kita membutuhkan library mysql ini agar bisa menghubungkan aplikasi spring-boot kita ke database mysql.
Langkah selanjutnya adalah kita akan mencoba membuat sebuah object model yang merupakan representasi entitas sebuah tabel dalam database. Kemudian validitas entitas tersebut nantinya juga akan kita test menggunakan spring-boot-starter-test yang sudah kita definisikan sebelumnya di file pom.xml, sebelum kita membuat entitas tersebut, terlebih dahulu kita susun struktur package dalam aplikasi percobaan kita ini. Buatlah struktur package seperti gambar berikut ini:


Pada gambar tersebut kita melihat kita membuat package org.josescalia.blog.simple pada folder src/main/java, dan org.josescalia.blog.simple.test pada folder src/test/java. Kemudian juga kita buat 3 package lain yang ada dalam package simple yaitu : config, model, dan repository. Struktur package ini biasa dibuat untuk mempermudah organisasi dalam pembuatan sebuah aplikasi java dan tentunya dengan tujuan-tujuan tersendiri, misal package model adalah package dimana seluruh class-class model data akan kita letakkan disini, atau package repository adalah class-class yang terhubung dengan database akan kita letakkan disini, dst-dstnya.
Kemudian mari kita buat sebuah object model dengan nama Author dan kita letakkan dalam package model. Adapun isi dari object model tersebut seperti dibawah ini:


package org.josescalia.blog.simple.model;
import javax.persistence.*;
/**
 * Created by josescalia on 25/10/15.
 */
@Entity
@Table(name = "AUTHOR")
public class Author {
    private Long id;
    private String authorName;
    private String authorAddress;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID", length = 11)
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    @Column(name = "AUTHOR_NAME", length = 100,nullable = false)
    public String getAuthorName() {
        return authorName;
    }
    public void setAuthorName(String authorName) {
        this.authorName = authorName;
    }
    @Column(name = "AUTHOR_ADDRESS", length = 255,nullable = true)
    public String getAuthorAddress() {
        return authorAddress;
    }
    public void setAuthorAddress(String authorAddress) {
        this.authorAddress = authorAddress;
    }
    @Override
    public String toString() {
        return "Author{" +
                "id=" + id +
                ", authorName='" + authorName + '\'' +
                ", authorAddress='" + authorAddress + '\'' +
                '}';
    }
}

Ok, sedikit saya jelaskan kode-kode diatas, object model yang kita buat ini merupakan sebuah class entity dengan nama Author. Class ini nantinya secara otomatis akan membuat sebuah tabel dalam database dengan nama tabel “AUTHOR”, dan field-field dalam tabel tersebut adalah ID, AUTHOR_NAME, AUTHOR_ADDRESS. Properti-properti dalam class  ini sudah dihubungkan dengan field-field tabel tersebut dengan menggunakan annotation @column. Buat yang terbiasa dengan penggunaan hibernate atau persistence programming dengan java, tentunya hal ini sudah tidak asing lagi bukan?
Langkah selanjutnya adalah kita akan membuat sebuah class yang bisa menghubungkan fungsi-fungsi CRUD (create, read, update, delete) dalam operasi database untuk object model Author ini. Dalam pemrograman aplikasi bisnis, class ini biasa disebut dengan DAO (Data Access Object), namun pada spring-boot, class ini lazim disebutkan dengan nama “repository”. Berarti kita akan membuat sebuah class dengan nama AuthorRepository dan letak class ini akan kita letakkan dalam package repository yang sudah kita buat sebelumnya. Adapun isi dari class ini adalah sebagai berikut:


package org.josescalia.blog.simple.repository;
import org.josescalia.blog.simple.model.Author;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
/**
 * Created by josescalia on 25/10/15.
 */
@Repository
public interface AuthorRepository extends CrudRepository<Author,Long> {
}

Class yang baru saja kita buat ini merupakan sebuah class interface yang meng-extend standard CRUD yang sudah disiapkan oleh spring-boot, artinya kita tidak perlu lagi membuat fungsi-fungsi standard CRUD, karena sudah dibuatkan oleh class CrudRepository milik spring-boot disana. Untuk tutorial ini kita batasi hanya menggunakan fungsi standard CRUD spring-boot saja dulu, untuk penggunaan lebih lanjut, bisa kita lanjutkan dalam tutorial lain nanti.
Seperti yang dijelaskan pada awal-awal tulisan ini, spring-boot menjanjikan tidak akan ada file konfigurasi xml dalam aplikasi yang menggunakan framework spring-boot ini. Tapi konfigurasi spring akan dilakukan dalam sebuah class juga. Maka langkah selanjutnya kita akan membuat class konfigurasi ini, kita beri nama DatabaseConfig dan class ini akan kita letakkan dalam package config. Adapun isi dari class ini adalah sebagai berikut:


package org.josescalia.blog.simple.config;

import org.apache.log4j.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Properties;
/**
 * Created by josescalia on 06/03/15.
 */
@Configuration
public class DatabaseConfig {
    static Logger logger = Logger.getLogger(DatabaseConfig.class.getName());

    @Scope(value = "singleton")
    public DataSource getDataSource() {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring-boot-learn");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(getDataSource());
        em.setPackagesToScan("org.josescalia.blog.simple.model");
        //
        final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(additionalProperties());
        return em;
    }

    @Bean
    public PlatformTransactionManager transactionManager(final EntityManagerFactory emf) {
        final JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(emf);
        return transactionManager;
    }

    final Properties additionalProperties() {
        logger.info("additional properties invoked");
        final Properties hibernateProperties = new Properties();
        hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
        hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
        return hibernateProperties;
    }
}
Dalam class ini kita bisa lihat konfigurasi aplikasi dilakukan disini, connection string database yang dipakai, setting untuk behavior hibernate, package-package dalam aplikasi yang akan di-scan oleh spring-boot, dan lain-lain. Dalam contoh kode di atas, memang masih menggunakan metode hard-code (meng-kode properti secara langsung ke dalam file class) dengan tujuan agar kita paham dulu penggunaan spring-boot secara umum. Pada pengembangannya nanti connection string tersebut bisa kita rubah metodenya dengan menggunakan property file, agar jika ada perubahan dalam environment aplikasi kita tidak perlu me-recompile source code aplikasi namun cukup merubah nilai-nilai dalam property file saja.
Sampai disini sebetulnya inti aplikasi dengan implementasi spring-boot sudah selesai, hanya saja kita memerlukan mekanisme test untuk memvalidasi apakah yang kita buat ini bisa dijalankan atau tidak. Untuk tujuan tersebut spring-boot juga sudah menyiapkan sebuah library yang juga sudah kita masukkan sebelumnya dalam file pom.xml yaitu : spring-boot-starter-test, dengan library ini, kita bisa langsung membuat sebuah class yang merupakan class test dan langsung mengimplemetasi library Junit di dalamnya.

Untuk membuat mekanisme test dalam rangkaian aplikasi dengan spring-boot, kita harus membuat class utama yang akan membaca seluruh context spring application terlebih dahulu, agar seluruh rangkaian class-class test yang kita buat bisa membaca konfigurasi spring-context, buatlah sebuah class dengan nama ApplicationTest dan letakkan dalam folder src/test/java dan dalam package org.josescalia.blog.simple.test seperti gambar dibawah ini:
Adapun isi dari class ini sebagai berikut:


package org.josescalia.blog.simple.test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.orm.jpa.EntityScan;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import java.io.IOException;
/**
 * Created by josescalia on 25/10/15.
 */
@Configuration
@ComponentScan(basePackages = {"org.josescalia.blog.simple"})
@EntityScan(basePackages = "org.josescalia.blog.simple.model")
@EnableJpaRepositories(basePackages = {"org.josescalia.blog.simple.repository"})
@EnableTransactionManagement
public class ApplicationTest {

    @Autowired
    private ConfigurableApplicationContext context;

    public static void main(String[] args) throws IOException {
        ApplicationTest test = new ApplicationTest();
        test.getContext();
    }

    public void getContext(){
        this.context = SpringApplication.run(ApplicationTest.class);
    }
}
Bisa kita lihat di dalam class ini, Spring Context di inisialisasi dan dipakai dalam thread ketika aplikasi ini berjalan(meski hanya test).
Sekarang barulah kita bisa membuat sebuah class test untuk menguji validasi object model dan repository yang sudah kita buat sebelumnya. Buatlah sebuah class dengan nama AuthorRepositoryTest dan letakkan class tersebut dalam package org.josescalia.blog.simple.test.repository, kemudian isi dari class tersebut adalah seperti dibawah ini:

package org.josescalia.blog.simple.test.repository;
import org.josescalia.blog.simple.model.Author;
import org.josescalia.blog.simple.repository.AuthorRepository;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.stereotype.Component;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
 * Created by josescalia on 25/10/15.
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = org.josescalia.blog.simple.test.ApplicationTest.class)
@Component
public class AuthorRepositoryTest {

    @Autowired
    private AuthorRepository authorRepository;

    @Before
    public void initAuthor(){
        Author author = new Author();
        author.setAuthorName("Josescalia");
        author.setAuthorAddress("Jakarta");
        authorRepository.save(author);
    }

    @Test
    public void testAuthorRepository(){
        System.out.println("Testing author repository");
        Assert.assertEquals(1, authorRepository.count());
        Assert.assertEquals("Josescalia",authorRepository.findOne((long) 1).getAuthorName());
    }
}

Class AuthorRepositoryTest ini menggunakan class ApplicationTest sebagai Spring Application Configuration-nya, dalam artian spring context yang dipakai oleh class test ini adalah milik class ApplicationTest.
Kemudian jalankanlah unit test ini dengan perintah sebagai berikut:
mvn clean test

Dan hasil ditempat sayapun seperti dibawah ini, bagaimana dengan anda?

Untuk source code percobaan ini anda juga bisa mendownloadnya di sini.


Depok, 23 Januari 2015

Josescalia

1 comment:

Anonymous said...

tutorialnya lengkap ya nuhun banget om semoga ilmunya bermanfaat buat semua ijin sedot dan pelajari