REST untuk pengembang Java, Bagian 2: Istirahatkan untuk yang lelah

Restlet API open source mengurangi beban kerja yang terlibat dalam pembuatan dan penggunaan RESTful API di Java. Dalam artikel kedua dalam seri pengembang REST untuk Java ini, Brian Sletten memperkenalkan Anda pada Restlet dan menjelaskan contoh aplikasi dalam menerapkan antarmukanya ke dalam wadah servlet yang Anda gunakan saat ini, sambil juga mempersiapkan sistem di masa depan. Brian juga secara singkat memperkenalkan JSR 311: JAX-RS, upaya Sun untuk mengintegrasikan RESTful API dengan tumpukan Java EE.

Pengembang Java telah lama tertarik dengan gaya arsitektur REST, tetapi hanya sedikit yang telah menempuh jarak antara dunia objek yang sudah dikenal dan dunia sumber daya RESTful. Meskipun kami mungkin menyukai kenyataan bahwa layanan RESTful dapat diproduksi atau dikonsumsi oleh bahasa lain, kami benci harus mengonversi data ke dan dari aliran byte. Kami benci harus memikirkan HTTP saat menggunakan alat seperti Apache HTTP Client. Kami melihat dengan penuh kerinduan pada objek yang dibuat oleh wsdl2javaperintah, yang memungkinkan kami meneruskan argumen ke layanan SOAP semudah pemanggilan metode lain, menyapu detail pemanggilan layanan jarak jauh di bawah permadani. Dan kami menemukan model servlet menjadi sedikit terlalu terputus dari sumber daya yang diproduksi. Cukuplah untuk mengatakan itu sementara kita sudah bisa untuk membangun layanan yang tenang dari awal, ini bukanlah pengalaman yang menyenangkan.

REST untuk developer Java

Baca serialnya:

  • Bagian 1: Ini tentang informasi
  • Bagian 2: Istirahatkan bagi yang lelah
  • Bagian 3: NetKernel

Masalah politik terkadang memperparah rintangan teknis. Banyak manajer merasa bahwa layanan Web berbasis SOAP adalah cara yang ditentukan untuk membangun arsitektur berorientasi layanan (SOA) di Java EE. Ini berubah dengan munculnya aktivitas penting seperti JSR 311, JAX-RS: Java API for RESTful Web Services, yang akan Anda pelajari di artikel ini. Jika tidak ada yang lain, upaya ini melegitimasi pengembangan RESTful di ruang JEE.

Sementara itu, bantuan telah tiba. Dengan cara yang elegan, kerangka Restlet open source memudahkan untuk menghindari masalah pelik yang dapat timbul dari penggunaan teknologi JEE tradisional untuk membangun dan menggunakan layanan RESTful.

Akar restlet

Dalam upaya untuk mengatasi beberapa masalah teknis yang terlibat dalam melakukan REST dengan Java, Jérome Louvel, konsultan perangkat lunak Prancis, berusaha membuat kerangka kerja yang akan memberikan kesesuaian yang lebih alami. Dia pertama kali melihat lingkungan NetKernel sebagai titik awal. Sebanyak yang dia suka, itu tidak cocok untuk kerangka kerja yang berfokus pada API yang dia coba sediakan. Namun, pengalaman tersebut membantu memengaruhi pemikirannya tentang hal-hal yang dapat ditawarkan oleh lingkungan berorientasi REST. (Artikel berikutnya dalam seri ini akan mempelajari NetKernel lebih lengkap.)

Saat Louvel mengerjakan kerangka kerjanya, dia mengembangkan tiga tujuan:

  • Tindakan sederhana harus sederhana untuk penggunaan dasar. Default harus bekerja dengan sedikit usaha tetapi juga memungkinkan konfigurasi yang lebih kompleks.
  • Kode yang ditulis ke API ini harus portabel di seluruh kontainer. Meskipun sistem berbasis servlet dapat dipindahkan di antara kontainer seperti Tomcat, Jetty, dan IBM WebSphere, Louvel memiliki gambaran yang lebih besar. Spesifikasi Servlet terkait dengan HTTP dan model I / O pemblokiran. Dia ingin API miliknya dapat dipisahkan dari keduanya dan dapat diterapkan ke dalam container yang digunakan saat ini. Dia juga ingin mereka dapat digunakan dengan sedikit usaha dalam wadah alternatif dan yang muncul seperti Grizzly, AsyncWeb, dan Kerangka Sederhana.
  • Ini harus memperkaya tidak hanya sisi server yang menghasilkan antarmuka RESTful di Java, tetapi juga sisi klien. The HttpURLConnectionkelas dan Apache HTTP Client terlalu rendah tingkat untuk mengintegrasikan bersih suatu langsung ke sebagian besar aplikasi.

Dengan tujuan ini dalam pikirannya, dia mulai membuat Restlet API. Setelah beberapa tahun berubah, API menjadi stabil dan komunitas berkembang di sekitarnya. Saat ini, API inti memiliki basis pengguna yang dinamis, dan aktivitas signifikan sedang dilakukan untuk mendukung integrasi dengan perangkat dan inisiatif lain seperti JAX-RS. (Louvel sekarang berada dalam kelompok ahli JAX-RS.)

Dasar-dasar restlet

Sebuah server dasar dengan Restlet API tidak mungkin lebih mudah, seperti yang ditunjukkan pada Daftar 1.

Kode 1. Sebuah server dasar dengan Restlet

package net.bosatsu.restlet.basic; import org.restlet.Restlet; import org.restlet.Server; import org.restlet.data.MediaType; import org.restlet.data.Protocol; import org.restlet.data.Request; import org.restlet.data.Response; public class SimpleServer { public static void main(String[]args) throws Exception { Restlet restlet = new Restlet() { @Override public void handle(Request request, Response response) { response.setEntity("Hello, Java RESTafarians!", MediaType.TEXT_PLAIN); } }; // Avoid conflicts with other Java containers listening on 8080! new Server(Protocol.HTTP, 8182, restlet).start(); } }

Aplikasi ini tidak berbuat banyak (kecuali menyebarkan keceriaan), tetapi menunjukkan dua prinsip dasar Restlet. Pertama, hal-hal sederhana itu sederhana. Kegiatan yang lebih kompleks memang dimungkinkan, tetapi Anda hanya mengkhawatirkannya saat diperlukan. REST tidak kekurangan kemampuan untuk menegakkan keamanan, batasan, negosiasi konten, atau tugas penting lainnya. Itu sebagian besar tetap merupakan aktivitas ortogonal, sangat berbeda dari proses memenuhi RESTful API. Anda melapisi kompleksitas sesuai kebutuhan.

Kedua, kode dalam Daftar 1 dirancang untuk menjadi portabel di antara jenis wadah. Perhatikan bahwa itu tidak menentukan wadah. Restlets adalah sumber daya aktual yang pada akhirnya menanggapi permintaan. Tidak ada perbedaan antara container yang menangani request dan resource responder, seperti yang terdapat pada model servlet. Jika Anda mengetik kode ke dalam IDE dan menambahkan dependensi pada arsip org.restlet.jardan com.noelios.restlet.jar, Anda dapat menjalankan aplikasi dan akan melihat pesan log seperti ini:

Dec 7, 2008 11:37:32 PM com.noelios.restlet.http.StreamServerHelper start INFO: Starting the internal HTTP server

Arahkan browser ke //localhost:8182, dan Anda akan melihat sapaan ramah.

Di balik layar, org.restlet.jarberisi semua antarmuka utama untuk API ini. The com.noelios.restlet.jarberisi implementasi dasar interface ini dan memberikan standar HTTP kemampuan penanganan. Anda tidak ingin berproduksi dengan mesin HTTP ini, tetapi ini sangat nyaman untuk tujuan pengembangan dan pengujian. Anda tidak perlu memulai wadah utama untuk menguji kode RESTful Anda. Hasilnya, pengujian unit dan integrasi bisa menjadi lebih mudah.

Contoh di Listing 1 menggunakan banyak perilaku default untuk membuat Applicationinstance default (akan saya bahas Applicationdi contoh berikutnya) dan mendengarkan permintaan protokol HTTP pada port 8182. StreamServerHelperKelas mulai mendengarkan di port ini dan mengirimkan permintaan ke Restletinstance sebagai mereka masuk.

Tujuan Louvel untuk mendukung Java RESTful sisi klien juga dapat dicapai dengan mudah, seperti yang Anda lihat di Listing 2.

Kode 2. Klien Restlet

package net.bosatsu.restlet.basic; import java.io.IOException; import org.restlet.Client; import org.restlet.data.Protocol; public class SimpleClient { public static void main(String [] args) throws IOException { String uri = (args.length > 0) ? args[0] : "//localhost:8182" ; Client client = new Client(Protocol.HTTP); client.get(uri).getEntity().write(System.out); } }

Dengan SimpleServermasih berjalan, meluncurkan kode klien baru ini dengan dependensi JAR yang sama akan mencetak salam ramah ke konsol. Mencetak keluaran dengan gaya ini jelas tidak akan berfungsi untuk jenis MIME berorientasi biner tetapi, sekali lagi, ini adalah titik awal yang nyaman.

Contoh non-CRUD

Sebagian besar contoh REST pedagogis menunjukkan layanan CRUDish (Buat, Ambil, Perbarui, Hapus) di sekitar objek sederhana. Meskipun gaya itu pasti bekerja dengan baik dengan REST, itu sama sekali bukan satu-satunya pendekatan yang masuk akal - dan kebanyakan dari kita bosan dengan contoh CRUD. Contoh berikut menunjukkan dasar-dasar aplikasi Restlet dengan membungkus pemeriksa ejaan sumber terbuka Jazzy.

REST adalah tentang mengelola informasi, bukan meminta perilaku sewenang-wenang, jadi Anda perlu berhati-hati saat mempertimbangkan API berorientasi perilaku seperti Jazzy. Triknya adalah memperlakukan RESTful API sebagai ruang informasi untuk kata-kata yang ada dan tidak ada dalam kamus yang digunakan. Masalahnya dapat diselesaikan dengan berbagai cara, tetapi artikel ini akan mendefinisikan dua ruang informasi. /dictionarydigunakan untuk mengatur kata-kata dalam kamus. /spellcheckerdigunakan untuk menemukan saran untuk kata yang mirip dengan kata yang salah eja. Keduanya fokus pada informasi dengan mempertimbangkan ada atau tidaknya kata-kata dalam ruang informasi.

Dalam arsitektur RESTful, perintah HTTP ini dapat mengembalikan definisi kata dalam kamus:

GET //localhost:8182/dictionary/word

Ini mungkin akan mengembalikan kode tanggapan HTTP "Tidak Ditemukan" untuk kata-kata yang tidak ada dalam kamus. Dalam ruang informasi ini, tidak masalah untuk menunjukkan bahwa kata-kata tidak ada. Jazzy tidak memberikan definisi untuk kata-kata, jadi saya akan meninggalkan beberapa konten sebagai latihan untuk pembaca.

Perintah HTTP berikutnya ini harus menambahkan kata ke kamus:

PUT // localhost: 8182 / kamus / kata

Contoh ini digunakan PUTkarena Anda dapat mengetahui URI apa di /dictionaryruang informasi sebelumnya, dan mengeluarkan beberapa PUTs tidak akan membuat perbedaan. ( PUTadalah permintaan idempoten, seperti GET. Mengeluarkan perintah yang sama beberapa kali seharusnya tidak membuat perbedaan.) Jika Anda ingin menambahkan definisi, Anda dapat meneruskannya sebagai badan ke PUTpenangan. Jika Anda ingin menerima beberapa definisi dari waktu ke waktu, Anda mungkin ingin POSTdefinisi tersebut masuk, karena PUTmerupakan operasi penimpaan.

Jangan mengabaikan sinkronisasi

Untuk menjaga agar contoh tetap fokus, artikel ini tidak memberikan perhatian khusus pada masalah sinkronisasi. Jangan perlakukan kode produksi Anda begitu saja! Konsultasikan sumber daya seperti Java Concurrency in Practice untuk informasi lebih lanjut.

The Restletcontoh bahwa saya akan membuat kebutuhan untuk terikat ke ruang informasi yang tepat, seperti yang ditunjukkan pada Listing 3.

Kode 3. Pemeriksa ejaan RESTful sederhana

package net.bosatsu.restlet.spell; import com.swabunga.spell.event.SpellChecker; import com.swabunga.spell.engine.GenericSpellDictionary; import com.swabunga.spell.engine.SpellDictionary; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import org.restlet.data.Protocol; import org.restlet.*; public class SpellCheckingServer extends Application { public static String dictionary = "Restlet/dict/english.0"; public static SpellDictionary spellingDict; public static SpellChecker spellChecker; public static Restlet spellCheckerRestlet; public static Restlet dictionaryRestlet; static { try { spellingDict = new GenericSpellDictionary(new File(dictionary)); spellChecker = new SpellChecker(spellingDict); spellCheckerRestlet = new SpellCheckerRestlet(spellChecker); dictionaryRestlet = new DictionaryRestlet(spellChecker); } catch (Exception e) { e.printStackTrace(); } } public static void main(String [] args) throws Exception { Component component = new Component(); component.getServers().add(Protocol.HTTP, 8182); SpellCheckingServer spellingService = new SpellCheckingServer(); component.getDefaultHost().attach("", spellingService); component.start(); } public Restlet createRoot() { Router router = new Router(getContext()); router.attach("/spellchecker/{word}", spellCheckerRestlet); router.attach("/dictionary/{word}", dictionaryRestlet); return router; } }

After it builds up the dictionary instance and the spell checker, the Restlet setup in Listing 3 is slightly more complicated than in the earlier basic example (but not much!). The SpellCheckingServer is an instance of a Restlet Application. An Application is an organizational class that coordinates deployment of functionally connected Restlet instances. The surrounding Component asks an Application for its root Restlet by calling the createRoot() method. The root Restlet returned indicates who should respond to the external requests. In this example, a class called Routerdigunakan untuk mengirimkan ke ruang informasi bawahan. Selain melakukan pengikatan konteks, tindakan ini menyiapkan pola URL yang memungkinkan bagian "kata" dari URL tersedia sebagai atribut atas permintaan. Ini akan dimanfaatkan dalam Restlets yang dibuat di Daftar 4 dan 5.

The DictionaryRestlet, yang ditunjukkan pada Listing 4, bertanggung jawab untuk menangani permintaan untuk memanipulasi /dictionaryruang informasi.