Tutorial JSON-LD dan RabbitMQ di Java

ceefour 1,346 views 33 slides Oct 24, 2015
Slide 1
Slide 1 of 33
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33

About This Presentation

Project ini menggunakan Maven project management system, yang didukung oleh semua IDE Java termasuk IntelliJ IDEA, Eclipse, dan NetBeans.

Libraries utama yang digunakan:
1. Spring Boot, terutama:
* Spring Web untuk web support. Termasuk embedded web server yaitu Tomcat.
* Spring Data JPA untuk akse...


Slide Content

Tutorial JSON-LD & RabbitMQ di Java
Hendy Irawan
[email protected]
www.hendyirawan.com

Software yang Perlu Diinstall
1.Oracle JDK8:
http://www.oracle.com/technetwork/java/javase/downloads/index.html
2.IntelliJ IDEA Community:
http://www.jetbrains.com/idea/download
3.RabbitMQ (install Erlang OTP terlebih dahulu):
◦Erlang OTP: http://www.erlang.org/download.html
◦RabbitMQ for Windows: https://
www.rabbitmq.com/install-windows.html

RabbitMQ
1.Pastikan RabbitMQ Server jalan. Caranya: Start > RabbitMQ Command
Prompt. Ketik:
rabbitmqctl status
2.Enable plugin rabbitmq_management. Caranya: Di RabbitMQ Command
Prompt, ketik:
rabbitmq-plugins enable rabbitmq_management
3.Pastikan Anda bisa akses http://localhost:15672/ (user: guest, password:
guest)

Download Project tutorial-rabbitmq
1.Klik https://github.com/soluvas/tutorial-rabbitmq
2.Klik Download ZIP
3.Extract

Konfigurasi Maven Proxy
Khusus bagi koneksi proxy (seperti ITB). Bila tidak menggunakan
proxy, skip langsung ke slide selanjutnya.
Buat file C:\Users\<username>\.m2\settings.xml , isi dengan template
berikut. Perhatikan: Ganti bagian user dan pass sesuai akun AI3 Anda.
<?xml version="1.0" encoding="UTF-8"?>
<settings 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/settings-1.0.0.xsd">
<proxies>
<proxy>
<active>true</active>
<protocol>http</protocol>
<host>cache.itb.ac.id</host>
<port>8080</port>
<username>user</username>
<password>pass</password>
<nonProxyHosts>127.0.0.1|localhost|*.itb.ac.id|167.205.*.*</nonProxyHosts>
</proxy>
</proxies>
</settings>

Project tutorial-rabbitmq
1.Pastikan koneksi internet Anda aktif
2.Jalankan IntelliJ IDEA
3.Klik Import Project atau New > Project from
Existing Sources
4.Pilih folder project
5.Pilih Import project from external model > Maven
6.Centang:
1.Import Maven projects automatically
2.Automatically download:
◦ Sources
◦ Documentation
7.Klik Next sampai selesai

IntelliJ akan menanyakan SDK (ada di slide
selanjutnya)

Platform Settings > SDKs
Bila ditanya SDK, Anda perlu menambahkan JDK 8.
Add New SDK > Java

Name: 1.8

Contoh Path: C:\Program Files\Java\jdk1.8.0_60
(sesuai build number)

Struktur Project

Project ini menggunakan Maven project management system, yang didukung
oleh semua IDE Java termasuk IntelliJ IDEA, Eclipse, dan NetBeans.

saat ini Maven sedang mengunduh dependencies/libraries yang dibutuhkan oleh
project (oleh karena itu butuh koneksi Internet)

Libraries utama yang digunakan:

Spring Boot, terutama:
–Spring Web untuk web support. Termasuk embedded web server yaitu Tomcat.
–Spring Data JPA untuk akses database relational.

Apache Wicket untuk web UI

Jackson untuk dukungan format JSON-LD
●Camel sebagai message router, yang mendukung RabbitMQ component

Maven Project

Aktifkan Maven Project di sisi
kanan, dan pastikan tidak ada
error (merah-merah)

Bila masih ada error, proses
download mungkin masih
berlangsung atau ada masalah
koneksi

Coba klik Reimport All Maven
Projects (lihat gambar)

Run Project

Di view Project di sisi
kiri, pilih:

tutorial-rabbitmq
> src
> main
> java
> org.soluvas.tutorial.rabbitmq
> DaemonApp

Klik kanan di class
DaemonApp, klik
Run

Tampilan Web UI

Buka http://localhost:8080/

Mengirim JSON-LD ke RabbitMQ
Untuk menambah Place, kirimkan JSON-LD ke topic starter.place, caranya:
1.Buka RabbitMQ Management di http://localhost:15672/ (user: guest, password: guest)
2.Klik tab Exchanges
3.Klik exchange amq.topic
4.Masuk bagian Publish message, masukkan:

Routing key: starter.place

Payload:
{
"@type": "Place",
"name": "Warung Mamah",
"description": "Enak top markotop"
}
5.Klik Publish message.
6.Cek di web UI aplikasi bahwa place Warung Mamah telah ditambahkan.

Struktur Aplikasi

Untuk struktur dan cara kerja Maven, Spring
Boot & Wicket, Spring Data JPA akan
dibahas di tutorial lain (TODO)

Hanya membahas penggunaan libraries
berikut:

Jackson untuk dukungan format JSON-LD
●Camel sebagai message router, yang mendukung
RabbitMQ component

Cara Kerja Aplikasi
1)PlaceRepository diimplementasi oleh Spring Data JPA untuk mengelola tabel
place di RDBMS
2)RabbitMqConfig membuat ConnectionFactory untuk RabbitMQ Client
3)ToJson membuat Jackson ObjectMapper untuk konversi JSON-LD <-> Java object
4)AsError mengubah Exception bawaan Java menjadi object Error yang bisa dikonversi
ke JSON-LD
5)ProducerTemplate diimplementasi oleh Camel untuk mengirimkan message ke
RabbitMQ

kebetulan belum dipakai di tutorial ini
6)StarterRouter adalah fungsi utama:
1)mengambil JSON-LD Place dari topic starter.place
2)menyimpannya ke tabel place di RDBMS
3)mengembalikan JSON-LD berupa status berhasil (Status.java) atau gagal (Error.java)

pom.xml dependencies: Jackson
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>

<groupId>com.fasterxml.jackson.datatype<
/groupId>
<artifactId>jackson-datatype-
guava</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>

<groupId>com.fasterxml.jackson.datatype<
/groupId>
<artifactId>jackson-datatype-
joda</artifactId>
<version>2.6.3</version>
</dependency>

pom.xml dependencies: Camel
RabbitMQ Component
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot</artifactId>
<version>2.16.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-rabbitmq</artifactId>
<version>2.16.0</version>
</dependency>

StarterThing.java
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonTypeInfo(use= JsonTypeInfo.Id.NAME, property="@type")
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonSubTypes({
@JsonSubTypes.Type(name="Status", value=Status.class),
@JsonSubTypes.Type(name="Error", value=Error.class),
@JsonSubTypes.Type(name="Place", value=Place.class),
})
public interface StarterThing extends Serializable {
}

interface yang akan diimplementasikan oleh class Status, Error, dan Place

diberi Jackson annotations

@JsonInclude NON_NULL: hanya property yang diisi yang akan diserialize ke JSON-LD

@JsonTypeInfo “@type”: informasi class dimasukkan ke property “@type” sesuai standar
JSON-LD

@JsonIgnoreProperties: property yang tidak dikenali tidak akan menimbulkan error
●@JsonSubTypes: daftar class yang dikenali

Place.java & PlaceRepository.java
JPA @Entity ini berisi:
1)id - @GeneratedValue, long
2)name - varchar(255)
3)description - text
4)creationTime - timestamp
Digunakan sebagai object yang menyimpan
representasi row di tabel place dalam database SQL.

Place.java
@Entity
@EntityListeners(Place.PlaceListener.class)
@Table(indexes = {@Index(name="ik_place_creationtime", columnList = "creationtime")})
public class Place implements StarterThing {
public static class PlaceListener {
@PrePersist
public void setInitialValues(Place place) {
place.setCreationTime(new DateTime());
}
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String name;
@Column(columnDefinition = "text")
private String description;
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime creationTime;
...

RabbitMqConfig.java
@Configuration RabbitMqConfig ini bertugas untuk
membuat ConnectionFactory yang dibutuhkan
RabbitMQ Client untuk koneksi ke server RabbitMQ.
Konfigurasi koneksi RabbitMQ dibaca dari file
application.properties:
# RabbitMQ
amqp.host=localhost
amqp.username=guest
amqp.password=guest

RabbitMqConfig.java
@Configuration
public class RabbitMqConfig {
private static final Logger log = LoggerFactory.getLogger(RabbitMqConfig.class);
@Inject
private Environment env;
@Bean
public ConnectionFactory amqpConnFactory() {
final ConnectionFactory connFactory = new ConnectionFactory();
connFactory.setHost(env.getRequiredProperty("amqp.host"));
connFactory.setUsername(env.getRequiredProperty("amqp.username"));
connFactory.setPassword(env.getRequiredProperty("amqp.password"));
log.info("AMQP configuration: host={} username={}", connFactory.getHost(),
connFactory.getUsername());
return connFactory;
}
}

ToJson.java
@Service ToJson bertugas:
1.Membuat instance ObjectMapper
(fungsi utama Jackson)
2.Digunakan oleh Camel Router untuk
mengkonversi object Java menjadi format
JSON-LD (String)

ToJson.java
@Service
public class ToJson implements Function<Object, String> {
protected ObjectMapper mapper;
public ToJson() {
mapper = new ObjectMapper();
mapper.registerModule(new JodaModule());
mapper.registerModule(new GuavaModule());
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}
@Override
public String apply(@Body Object o) {
try {
return o != null ? mapper.writeValueAsString(o) : null;
} catch (JsonProcessingException e) {
Throwables.propagate(e);
return null;
}
}
public ObjectMapper getMapper() {
return mapper;
}
}

StarterRouter.java
●@Component ini extends base class yang disediakan Camel yaitu
RouteBuilder
●Method configure() harus di-override, yang berisi definisi route
●Route merupakan instruksi kepada Camel untuk:
–mengambil message dari endpoint tertentu, dalam hal ini
RabbitMQ Component
–melakukan pengolahan
–melakukan konversi dari/ke JSON-LD via Jackson
–menampilkan log (bila perlu)
–mekanisme penanganan kesalahan

StarterRouter: Penanganan Kesalahan
onException(Exception.class).bean(asError).bean(toJson).handled(true);
errorHandler(new LoggingErrorHandlerBuilder(log));
Code tersebut:
●bila terjadi Exception di dalam route:

akan diserahkan ke bean asError, yang akan mengubah Exception
menjadi object Error

akan diserahkan ke bean toJson, yang akan mengkonversi object Error
menjadi JSON-LD String

menandai handled=true, bahwa kesalahan sudah ditangani oleh code kita

bila Camel mendeteksi error:

tampilkan dalam log menggunakan LoggingErrorHandlerBuilder

StarterRouter: Consume topic RabbitMQ
final String topic = "starter.place";
from("rabbitmq://dummy/amq.topic?
connectionFactory=#amqpConnFactory&exchangeType=topic&autoDe
lete=false&routingKey=" + topic)

Consume menggunakan konfigurasi RabbitMQ di bean
amqpConnFactory (lihat RabbitMqConfig.java)

Consume dari exchange amq.topic

Sifat exchange adalah autoDelete=false (exchange tidak akan
dihapus setelah dipakai)

Consume dari routing key starter.place

StarterRouter: Log input
.to("log:IN." + topic + "?
showHeaders=true&showAll=true&multiline=true")

Message input dari RabbitMQ consumer akan ditampilkan di
log dengan nama IN.starter.place

Tampilkan:

headers

semua isi message body

mendukung multiline

More info: http://camel.apache.org/log.html

StarterRouter: Mengolah message
.process(exchange -> {
final StarterThing thing =
toJson.getMapper().readValue(
exchange.getIn().getBody(byte[].class),
StarterThing.class);
if (thing instanceof Place) {
Place place = (Place) thing;
log.info("Saving {} ...", place);
place = placeRepo.save(place);
// reply
exchange.getIn()
.setBody(new Status(place));
} else {
// unknown thing, ignore
exchange.getOut().setBody(null);
}
})

Gunakan Jackson untuk mengkonversi
message body (byte[]) menjadi
StarterThing

interface StarterThing bisa
diimplementasi oleh class yang berbeda-
beda
●Bila thing adalah class Place, maka:

gunakan placeRepo untuk menyimpan
Place tersebut ke RDBMS

mengembalikan Status berisi data Place
yang sudah update

Bila thing tidak dikenali, maka:

set exchange out menjadi null

dengan mengeset exchange out, maka
reply tidak akan dikirimkan

StarterRouter: Konversi reply ke JSON-LD
.bean(toJson)

Gunakan Jackson
untuk mengkonversi
reply (bila ada)
bertipe Status atau
Error menjadi
JSON-LD String

StarterRouter: Konversi reply ke JSON-LD
.to("log:OUT" + topic);

Optional

Reply akan
ditampilkan di log
dengan nama
OUT.starter.plac
e sebelum dikirim
ke RabbitMQ

Dependencies Tambahan

Tidak wajib, tapi berguna karena umum dipakai

commons-codec & jdatauri

Belum dipakai di tutorial ini

pom.xml dependencies:
commons-codec & jdatauri
commons-codec
mendukung berbagai macam
codec, termasuk Base64
yang umum dipakai oleh
Data URI
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.8</version>
</dependency>
jdatauri untuk parsing
Data URI
<dependency>
<groupId>com.github.ooxi</groupId>
<artifactId>jdatauri</artifactId>
<version>1.0</version>
</dependency>

Pertanyaan / Kesulitan?
Silakan email [email protected]