Skip navigation

Category Archives: Java


For quite some time I’ve been looking for a very easy way to deploy a small service using Java that is accessible through HTTP and self-hosted, or in other words, it doesn’t need a installed server. I was initially thinking about using embedded Tomcat or Jetty by writing the server code manually.

But then it turns out that there is this project from Spring built specifically for this kind of application: the Spring Boot. As quoted from the web,

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that can you can “just run”.

By using this framework, I only need to focus on building the service rather than writing the HTTP server. And running the service is just as simple as using plain old `java -jar`.

The whole source code can be seen in this URL https://github.com/petrabarus/springboot-opsworks-example.

I started by using the sample code from Spring Boot.

import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;

@Controller
@EnableAutoConfiguration
public class SampleController {

    @RequestMapping("/")
    @ResponseBody
    String home() {
        return "Hello World!";
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(SampleController.class, args);
    }
}

The skeleton code for the controller can not be much simpler than this.

And here’s the POM file.

<?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>net.petrabarus.maleskoding</groupId>
    <artifactId>springboot-opsworks-example</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.1.6.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <!-- Sets to use Jetty. No particular reasons -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>
        <dependency>
            <!-- For deployment ready -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <resource>
                <!-- Creates directory for OpsWorks config -->
                <directory>src/deploy</directory>
                <targetPath>../deploy</targetPath>
            </resource>
            <resource>
                <!-- Creates config directory for external config --> 
                <directory>src/config</directory>
                <targetPath>../config</targetPath>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <!-- Creates JAR -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <!-- Creates zip distributable -->
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <descriptor>src/assembly/dep.xml</descriptor>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>
</project>

The XML code below is the minimum configuration to run the service. (The spring-boot-starter-jetty is used to make the service runs using Jetty instead of the default embedded Tomcat).

<!-- cut -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.1.6.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <!-- Sets to use Jetty. No particular reasons -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>

<!-- cut -->

To build the JAR, I use this plugin

<!-- cut -->
    <build>
        <!-- cut -->
        <plugins>
            <plugin>
                <!-- Creates JAR -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
<!-- cut -->

Building the JAR is simply just by executing

$mvn clean install

and the JAR will be in the `target` directory, e.g. target/springboot-opsworks-example-1.0-SNAPSHOT.jar I run it using the usual java -jar command

$target/springboot-opsworks-example-1.0-SNAPSHOT

I can see the result by using curl

$curl localhost:8080
Hello World!

Now it’s time to deploy it using OpsWorks. In this example I use `HTTP archive`, but it’s better to use `S3 archive` to provide better security since it can use IAM credentials.

Screenshot from 2014-09-20 00:02:21

The ZIP-ed file for deployment can be created using `spring-boot-maven-plugin`

<!-- cut -->
    <build>
        <!-- cut -->
        <plugins>
            <plugin>
                <!-- Creates zip distributable -->
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <descriptor>src/assembly/dep.xml</descriptor>
                </configuration>
            </plugin>
<!-- cut -->

Here’s the assembly XML configuration

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
    <id>bin</id>
    <formats>
        <format>zip</format>
    </formats>
    <fileSets>
        <fileSet>
            <directory>${project.build.directory}</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>*.jar</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>${project.build.directory}/config</directory>
            <outputDirectory>config</outputDirectory>
            <includes>
                <include>*.xml</include>
                <include>*.properties</include>
                <include>*.yml</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>${project.build.directory}/deploy</directory>
            <outputDirectory>deploy</outputDirectory>
        </fileSet>
    </fileSets>
</assembly>

Now I can have a very simple build and distribution script like below. This can be use for Jenkins. When a new change is pushed to the git repository, Jenkins will download the change, build, test the source, and then pack and upload the binary.

$mvn clean install assembly:single && s3cmd put -P target/*.zip s3://path/to/the/upload.zip

As we know, deploying in OpsWorks is just a matter of click.

Screenshot from 2014-09-20 00:02:07

Note that deploying the OpsWorks app doesn’t mean running the service automatically. For that I need to use a deploy hook. Chef provides a way to execute a ruby script on steps in the deployment. Using the `before_restart.rb` I can execute a task that happens after the app directory changes its link from the old directory to the new deployed directory.

The content of `before_restart.rb` script is in below

script "runjar" do
    interpreter "bash"
    user "root"
    cwd release_path
    code <<-EOH
        java -jar *.jar > /var/log/springbootext1/app.log 2>&1 &
    EOH
end

I added the file in the `src/deploy` directory and I declare it as a resource in the POM file.

    <build>
        <resources>
            <resource>
                <!-- Creates directory for OpsWorks deploy hook -->
                <directory>src/deploy</directory>
                <targetPath>../deploy</targetPath>
            </resource>

The next question is how to shutdown the running service and update the new JAR. Spring Boot provides a production-ready feature called the actuator. Here I can put a shutdown for the service that will turn off the running service. To add the actuator, I define the dependency in the POM file.

<!-- cut -->
        <dependency>
            <!-- For deployment ready -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
<!-- cut -->

And in the deploy hook, before the run service script I added new script

script "shutdown" do
    interpreter "bash"
    user "root"
    cwd release_path
    code <<-EOH
        curl -XPOST "http://localhost:8080/shutdown" > /var/log/springbootext1/app.log 2>&1
    EOH
end

That script send a POST request to the current running service to shut itself down. As default the shutdown actuator is not enabled by default. I still need to add new configuration. To do this, I added a new file `scr/config/application.properties` and I added this line.

endpoints.shutdown.enabled=true

Spring Boot has a very flexible way of configuring the application. The simplest way is to have `config/application.properties` file in the JAR directory. The application JAR will check what’s inside the file and override the configuration.

The deploy directory also needs to be declared as resource in the POM file

<!-- cut -->
    <build>
        <resources>
            <!-- cut -->
            <resource>
                <!-- Creates config directory for external config --> 
                <directory>src/config</directory>
                <targetPath>../config</targetPath>
            </resource>
        </resources>
            <!-- cut -->

So now I have a minimum skeleton for deploying a small standalone HTTP service. Keep in mind to restrict the 8080 port by using AWS Security Group so that the 8080 port is only accessible to appropriate instances.

Regarding the deployment, I’m guessing there will be few seconds downtime between the shutdown and running new service. This can be even much longer if I put some long task in the shutdown listener. I’m still thinking how to do this more seamlessly. Ideas needed 😉

Another thing I can do is passing the custom JSON in the OpsWorks to the `application.properties` configuration file.

I can define something like this.

{
    "springboot-example": {
        "config": {
            "server.port" : 3333,
            "management.port": 3334
        }
    }
}

It’s a good idea to make the server port and the management port more configurable among other things. And I can write that JSON in the `application.properties` using the deploy hook `before_symlink.rb` and modify the `before_restart.rb` to use the custom JSON for the port numbers. This is very flexible since I can define the custom JSON in the Stack level and also in the deployment level.

Iklan

Setelah lama dinanti-nanti, JUG Bandung kembali mengadakan Java User MeetUp. Di MeetUp kali ini kita akan membahas mengenai sistem operasi mobile “Android” yang hingga kini gadgetnya sudah bertebaran dan  makin populer bagi para pengguna. Tentu saja kepopuleran ini adalah potensi sangat besar yang tidak boleh dilewatkan oleh pengembang.

Dengan format yang berbeda dengan sebelumnya, MeetUp kali ini akan diisi oleh tiga perusahaan startup yang sedang mengembangkan produk berbasis Android: Javan IT Service, GITS Indonesia, dan Agate Studio.

Selain itu juga akan ada presentasi mengenai OSS-FEST, sebuah acara festival dan kompetisi aplikasi mobile berbasis Android. (ossfest-indonesia.web.id)

Acara ini terbuka bagi siapa saja dan tidak dipungut biaya. Acara diadakan pada
Hari : Jumat, 15 Oktober 2010
Waktu : 18.00 s.d. 20.00
Tempat: Ruang 7602, Gedung Labtek Benny Subianto lt 3 ITB
(Jalan Ganesha no 10)

Harap konfirmasi kehadiran di http://on.fb.me/9nMd5j


Menanggapi banyak permintaan untuk mengadakan pendalaman materi GWT yang telah diberikan pada JAMU Bandung Mei  2010 maka dengan ini pengurus JUG-Bandung mengadakan acara

JUG-BANDUNG WORKSHOP JUNI 2010

“Pembangunan Sistem Informasi Rumah Sakit Sederhana Menggunakan Google Web Toolkit“

Pada workshop ini peserta akan diberi pelatihan mengenai penggunaan GWT untuk studi kasus pembangunan sistem informasi rumah sakit sederhana.

Detail acara

Tanggal : Sabtu 5 Juni 2010
Waktu : 09.00 s.d. 15.00
Tempat : Lab 1, Gedung Ilmu Komputer Universitas Pendidikan Indonesia
Biaya : Rp40.000 per orang
Fasilitas : CD, Hardcopy modul, lunch, sertifikat
(Untuk kenyamanan peserta diharapkan membawa laptop masing-masing)

==================================================================
Pendaftaran dilakukan dengan mengirimkan data diri ke email
petra.barus@gmail.com dengan subject “Workshop JUG-Bandung”
berisi

Nama :____________
Instansi :____________
Handphone :____________
==================================================================
Pembayaran dilakukan dengan transfer ke nomor rekening berikut:

BCA KCU Matraman
No Rekening : 3422837911
Atas Nama : Petra Noviandi

Mandiri KCP Pulomas
No Rekening : 1200004735481
Atas Nama : Petra Novandi

BNI Kantor Cabang ITB Bandung
No Rekening : 0108995890
Atas Nama : Eko Kurniawan K

==================================================================
Setelah transfer kirim konfirmasi ke email petra.barus@gmail.com berisi

Tanggal Bayar :_____________
Bank :_____________
No. Rekening :_____________
==================================================================

First pay, first serve ^_^
Kuota peserta 30 orang. Kalau permintaan banyak maka akan
dipertimbangkan pengadaan kloter selanjutnya.
Daftar peserta yang sudah fix akan diumumkan di situs group

Diskusi dapat dilakukan di milis JUG-Bandung
http://groups.google.co.id/group/jug-bandung

Konfirmasikan Keharidan Anda di :
http://www.facebook.com/event.php?eid=104793552900556


Untuk membuat sebuah JFrame menjadi fullscreen hanya perlu dengan 2 baris kode di bawah.

Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setBounds(0, 0, screenSize.width, screenSize.height);

JFrame akan menjadi memenuhi layar. Tapi mungkin masih kurang karena titlebar dari JFrame masih akan terlihat. Untuk itu tinggal eksekusi method setUndecorated dengan nilai true sebelum JFrame ditampilkan.

Cara ini juga dapat diterapkan pada JDialog.


Taekwondo Tournament Management System atau Taekwondo TMS adalah sebuah perangkat lunak manajemen pertandingan Taekwondo. Perangkat lunak ini saya kembangkan berkerja sama dengan Wayang Sports, sebuah lembaga usaha yang dirintis oleh rekan saya yang bergerak di dalam usaha penyediaan perangkat-perangkat dijital untuk penyelenggaraan acara-acara olahraga.

Fungsi-fungsi aplikasi ini antara lain pembuatan turnamen, manajemen kelas-kelas turnamen serta peserta, serta manajemen bagan pertandingan. Fitur menarik dari aplikasi ini adalah aplikasi ditemani dengan perangkat keras yang dikembangkan oleh Wayang Sport untuk digunakan oleh juri dalam menilai pertandingan. Penjurian ini dilakukan secara realtime dan akan ditampilkan langsung oleh aplikasi. (contoh tampilan terlampir pada slide berikut)

Aplikasi Taekwondo TMS dikembangkan dengan menggunakan teknologi Netbeans Platform. Penggunaan teknologi ini sangat menguntungkan karena desainnya yang modular sehingga menjadikan aplikasi Taekwondo TMS ini dapat hanya menjadi satu sub-aplikasi dari banyak sub-sub aplikasi manajemen pertandingan untuk cabang-cabang lain yang terkemas dalam sebuah aplikasi besar. Selain penambahan modul-modul aplikasi per cabang, aplikasi besar ini nantinya akan ditambah fitur-fitur yang terintegrasi dengan media-media sosial seperti Facebook dan lain-lain.


Sebagai salah satu dari banyak komunitas berbasis pengembang perangkat lunak, komunitas Java User Group Bandung (JUG-Bandung) memiliki motivasi untuk saling berbagi ilmu di antara anggotanya. Motivasi ini lah yang mendorong JUG-Bandung untuk mengadakan acara Java User Meetup (JAMU) untuk pertama kalinya. Acara ini diselenggarakan hari Sabtu 8 Mei 2010 lalu di Labtek Benny Subianto, ITB. Terselenggaranya acara ini adalah hasil kerja sama dengan Open Source User Meetup (OSUM) ITB dan Himpunan Mahasiswa Informatika (HMIF) ITB. Read More »


Java User Meetup atau JaMU adalah acara yang diadakan oleh Java User Group untuk belajar bersama mengenai sebuah topik dalam teknologi berbasis Java. JUG Bandung juga akan menginisiasi pengadaan acara serupa secara rutin untuk komunitas pengguna Java di kota Bandung dan tidak tertutup juga untuk kota-kota lain di provinsi Jawa Barat.

Tema yang diangkat kali ini adalah mengenai Google Web Toolkit (GWT). GWT adalah sebuah perangkat pengembangan aplikasi internet menggunakan AJAX. Topik ini akan dibawa oleh Muhammad Ghazali (Pengurus JUG Bandung)

Selain dari sharing knowledge tersebut, akan ada acara ramah tamah anggota komunitas dan juga sharing/brainstorming visi, misi, dan kegiatan JUG Bandung.

Acara akan diadakan pada
Hari : Sabtu, 8 Mei 2010
Waktu : 09.00 pagi s.d. selesai
Tempat: Ruang 7602, Gedung Labtek Benny Subianto lt. 3 Institut Teknologi Bandung

Kehadiran tidak dipungut biaya.

Harap konfirmasi kehadiran di
http://www.facebook.com/event.php?eid=113889095314931

Milis JUG-Bandung http://groups.google.com/group/jug-bandung


Mungkin gw udah cerita di beberapa post lalu kalau pada semester ini gw mengambil mata kuliah Sistem Rekognisi. Permasalahan yang dihadapi kali ini adalah bagaimana menipiskan ketebalan sebuah gambar pada karakter yang ingin direkognisi. Penipisan ini dilakukan untuk mengambil fitur-fitur penting dari karakter tersebut. Algoritma ini disebut thinning. Keterangan lebih lanjut bisa dibaca di sini.

Algoritma yang gw gunakan di sini adalah algoritma yang dikemukakan oleh Zhang-Suen dalam paper mereka yang berjudul “A Fast Parallel Algorithm For Thinning Digital Pattern“. Read More »


Satu hal yang buat gw menyebalkan adalah membuat sebuah JFrame dengan tampilan yang mewah penuh warna-warni, rupa, bentuk, dan gambar tapi mudah digunakan untuk resolusi layar ataupun ukuran JFrame yang fleksibel. Salah satu solusi yang gw gunakan adalah dengan menggunakan SVG. SVG adalah format grafik vektor yang diimplementasikan dengan menggunakan XML. Karena itu SVG mudah digunakan baik dalam penampilan maupun dalam manipulasi gambar yang ditampilkan. Read More »


Kemarin saya dijebak diminta untuk mengisi pelatihan Java untuk OSUM UPI. Saya membawa sesi terakhir dari 6 sesi pelatihan. Pelatihan ini diadakan setiap Sabtu selama 3 minggu di mana setiap hari terdapat 2 sesi. Pelatihan ini ditujukan bagi mahasiswa UPI dan untuk tingkat pemula. Awalnya saya dijebak diminta untuk mengisi materi Netbeans Platform. Tapi agaknya terlalu jauh melompat tingkatnya. Akhirnya saya menawarkan mengisi materi konkurensi di Java.

Materi yang saya bawakan adalah pengantar konkurensi. Saya mengenalkan tentang Thread dan fitur-fitur manajemen Thread yang disediakan oleh Java seperti sleep, interrupt, join, dan wait (yang terakhir ditambahkan di detik-detik terakhir). Selain itu saya juga mengenalkan metode untuk sinkronisasi antar Thread. Dan terakhir saya menyinggung sedikit mengenai Timer.

Modul pelatihan dan slide presentasi dapat dilihat di bawah.

Read More »

%d blogger menyukai ini: