Monday, December 14, 2015

Spark dan Spring

Spark merupakan mikro framework berbasis Java untuk membangun aplikasi berbasis web.
Spark juga dapat digunakan untuk membangun RESTful API.

Spark terinsipirasi dari framework Sinatra dalam bahasa Ruby.

Quick Start

import static spark.Spark.*;

public class HelloWorld {
    public static void main(String[] args) {
        get("/hello", (req, res) -> "Hello World");
    }
}

Ya, contoh sederhana membuat REST API "Hello World" cukup dengan code seperti diatas. Run class tersebut, maka akan muncul :

[Thread-0] INFO org.eclipse.jetty.util.log - Logging initialized @261ms
[Thread-0] INFO spark.webserver.JettySparkServer - == Spark has ignited ...
[Thread-0] INFO spark.webserver.JettySparkServer - >> Listening on 0.0.0.0:4567
[Thread-0] INFO org.eclipse.jetty.server.Server - jetty-9.3.2.v20150730
[Thread-0] INFO org.eclipse.jetty.server.ServerConnector - Started ServerConnector@74b16130{HTTP/1.1,[http/1.1]}{0.0.0.0:4567}
[Thread-0] INFO org.eclipse.jetty.server.Server - Started @434ms

Test curl atau buka browser dengan url http://localhost:4567/hello maka akan mengembalikan "Hello World"

Integrasi Spark & Maven

Tambahkan spark library pada pom.xml
<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-core</artifactId>
    <version>2.3</version>
</dependency>

Integrasi Spark & Spring

Tambahkan spring library pada pom.xml
<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-core</artifactid>
    <version>4.1.7.RELEASE</version>
</dependency>
<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-context</artifactid>
    <version>4.1.7.RELEASE</version>
</dependency></code>

Buat file spring context bernama Beans.xml didalam folder main/resources
<?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"
       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">

    <context:component-scan base-package="org.nostratech.spark" />

    <bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
        <property name="driverClass" value="org.hsqldb.jdbcDriver" />
        <property name="jdbcUrl" value="jdbc:hsqldb:mem:unit-testing-jpa:9001:test" />
        <property name="username" value="sa"/>
        <property name="password" value=""/>
        <property name="idleConnectionTestPeriodInMinutes" value="1"/>
        <property name="idleMaxAgeInMinutes" value="4"/>
        <property name="maxConnectionsPerPartition" value="60"/>
        <property name="minConnectionsPerPartition" value="20"/>
        <property name="partitionCount" value="3"/>
        <property name="acquireIncrement" value="10"/>
        <property name="statementsCacheSize" value="50"/>
    </bean>

</beans>

Didalam file Beans.xml kita memiliki data source untuk koneksi ke database HSQL, dan konfigurasi supaya spring men-scan bean yang ada di package tertentu. Setelah itu kita load di main class menggunakan cara sebagai berikut :

public class Main {
    public static void main(String[] args) {
        //load spring context
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Beans.xml");
        //ambil spring bean
        BookService bookService = (BookService) applicationContext.getBean("bookService");
        //assign ke spark
        new BookController(bookService);
    }
}

Berikut class BookController tempat mendefine route / endpoint REST API.
public class BookController {

    Gson gson = new Gson();

    public BookController(final BookService bookService) {

        post("/book", (request, response) -> {

            // process request
            final Book book = gson.fromJson(request.body(), Book.class);

            RequestHandler requestHandler = new RequestHandler() {
                @Override
                public Object processRequest() {
                    return bookService.post(book);
                }
            };

            response.status(200);
            response.type("application/json");
            return requestHandler.getResult("OK");
        });
        
        //tambahkan route yang lain seperti get, put, atau delete
    }
}

Untuk menangani masalah ke database saya menggunakan library sql2o pada class BookService, berikut potongannya :
@Component("bookService")
public class BookService implements CRUDService<Book> {

    @Autowired
    DataSource dataSource;

    @Override
    public Boolean post(Book book) {

        int result;

        if (book.getId() == null) book.setId(UUID.randomUUID().toString());

        Sql2o sql2o = new Sql2o(dataSource);

        String sql = "INSERT INTO BOOK (SID, TITLE, AUTHOR) VALUES (:sid, :title, :author);";

        try (Connection con = sql2o.open()) {
            result = con.createQuery(sql)
                    .addParameter("sid", book.getId())
                    .addParameter("title", book.getTitle())
                    .addParameter("author", book.getAuthor())
                    .executeUpdate().getResult();
        }

        return (result > 0);
    }

    //tambahkan logic yang lain disini
}

Untuk mem-bundle aplikasi ini dalam bentuk jar, tambahkan maven-assembly-plugin pada pom.xml

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <mainClass>com.nostratech.spark.BlogService</mainClass>
            </manifest>
        </archive>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
    <executions>
        <execution>
        <id>make-assembly</id> <!-- this is used for inheritance merges -->
            <phase>package</phase> <!-- bind to the packaging phase -->
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Bentuk jar dengan perintah mvn clean package, file jar dan library dependency akan terbentuk didalam folder target.

Jalankan dengan perintah java -jar {nama file}
Run aplikasi dengan java -jar
Source code aplikasi bisa diakses di https://bitbucket.org/agus3winarno/spark-sample

Semoga bermanfaat, Happy coding :)

referensi :

No comments:

Post a Comment