Skip to main content
•9 min read

Java'da Web Servis Geliştirme: JAX-RS ve JAX-WS

Mustafa Kürşad BaşerMustafa Kürşad BAŞER
••
Java'da Web Servis Geliştirme: JAX-RS ve JAX-WS
Java Web Servis Geliştirme
Java Web Servis Geliştirme

Java tarafında bir web servis yazacaksanız önünüze iki isim çıkar: JAX-RS ve JAX-WS. İkisi de aynı platformdan gelir ama tamamen farklı dünyalara aittir. Biri REST konuşur, diğeri SOAP. Aşağıda ikisini de e-ticaret örneği üzerinden ele alacağım, sonunda da hangisinin ne zaman seçileceğine geleceğim.

Başlamadan önce: API nedir?

API (yani Application Programming Interface) farklı yazılımların birbirleriyle iletişim kurmasını sağlayan bir arayüzdür. Basitçe ifade etmek gerekirse, bir uygulamanın diğer bir uygulamadaki özellikleri kullanabilmesini sağlayan bir köprüdür.

Bir uygulama bir diğer uygulamadaki bir özelliği kullanmak istediğinde, API sayesinde bu özellik kullanılabilir hale gelir. Örneğin, bir mobil uygulama harita servisini kullanmak istediğinde, harita sağlayıcısının API’si aracılığıyla bu hizmete erişir. Böylece, API’ler, uygulama geliştiricilerinin kodlarını yeniden kullanmalarına ve kaynaklarını daha verimli bir şekilde yönetmelerine olanak tanır.

Benzer şekilde, bir web sitesi, bir başka web sitesindeki haberleri veya hava durumu bilgilerini göstermek istediğinde, ilgili sitenin API’si sayesinde bu verilere kolayca erişebilir.

Bu konuda daha detaylı bilgi edinmek için serinin bir önceki yazısı SOAP ve REST API: Nedir, Farklılıklar, Avantajlar ve Dezavantajlar yazıma göz atmanızı öneririm.

JAX-RS Nedir?

JAX-RS, Java ile RESTful servis yazmak için tanımlanmış bir spesifikasyon. Dikkat edin, kütüphane değil spesifikasyon: kendisi bir şey yapmaz, uyulacak kuralları belirler. Onu hayata geçiren uygulamalar ayrıdır ve en bilinenleri Jersey ile RESTEasy’dir. Projenize eklediğiniz de bunlardan biri olur.

Çalışma şekli anotasyon temelli. Sıradan bir Java sınıfı yazarsınız, metotlarının üzerine @GET ya da @POST koyarsınız, sınıfın başına da @Path ile adresini yazarsınız. Gerisini çalışma zamanı halleder: gelen isteğin yolunu ve metodunu eşleştirip doğru metodu çağırır, dönüş değerini de JSON veya XML’e çevirir.

Örnek: E-Ticaret Platformu

Bir e-ticaret uygulaması üzerinden gidelim. İki uç noktaya ihtiyacımız var: ürünleri listeleyen bir okuma ucu ve sipariş oluşturan bir yazma ucu.

1. Ürünleri Listeleme:

Listeleme tarafı için bir ProductResource sınıfı yazıyoruz. İçindeki metot GET isteklerini karşılayacak ve ürün listesini dönecek.

java
import javax.ws.rs.*;import javax.ws.rs.core.MediaType;import java.util.List; // Ürünleri listelemek için kullanılacak olan RESTful servis@Path("/products")public class ProductResource {     // GET isteğini işleyen metot    @GET    @Produces(MediaType.APPLICATION_JSON)    public List<Product> getProducts() {        // Gerçekleştirilecek işlemler        return productService.getAllProducts(); // Ürünleri veritabanından al ve JSON formatında döndür    }}

2. Sipariş Verme:

Sipariş tarafı ise POST bekliyor, çünkü sunucuda yeni bir kayıt yaratıyor. Aynı adrese GET atmak siparişleri listelerdi; adres aynı, fiil farklı.

java
import javax.ws.rs.*;import javax.ws.rs.core.MediaType; // Siparişleri işlemek için kullanılacak olan RESTful servis@Path("/orders")public class OrderResource {     // POST isteğini işleyen metot    @POST    @Consumes(MediaType.APPLICATION_JSON)    @Produces(MediaType.APPLICATION_JSON)    public Order placeOrder(Order newOrder) {        // Gerçekleştirilecek işlemler        return orderService.processOrder(newOrder); // Yeni siparişi işle ve onayla, ardından oluşturulan siparişi döndür    }}

İki sınıfta da dikkat çeken şey ne kadar az kod olduğu. Ortada HTTP okuyan, gövde ayrıştıran ya da yanıt yazan tek satır yok; hepsini anotasyonlar üstleniyor.

Anotasyonları tek tek görelim. @Path adresi belirler ve sınıf üzerinde de metot üzerinde de kullanılabilir; ikisi varsa yollar birleşir. @GET ve @POST hangi HTTP metoduna cevap verileceğini söyler. @Produces yanıtın formatını, @Consumes ise kabul edilen istek gövdesinin formatını belirtir. @Produces yazmayı unutursanız sunucu içeriği tahmin etmeye çalışır ve genelde istediğiniz sonucu vermez.

Spesifikasyon olmanın pratik faydası taşınabilirlik: kodunuz Jersey ile yazılmış olsa da RESTEasy kullanan bir sunucuda çalışır, çünkü ikisi de aynı sözleşmeye uyar.

JAX-WS Nedir?

JAX-WS ise madalyonun diğer yüzü: XML tabanlı, yani SOAP konuşan servisler için. Buradaki temel fark yaklaşımda. JAX-RS’te adresleri ve HTTP fiillerini düşünürsünüz, JAX-WS’te ise uzaktaki bir nesnenin metodunu çağırıyormuş gibi çalışırsınız. Ağ katmanı gözden kaybolur.

SOAP’ın getirdiği ek yetenekler de var: WS-Security ile mesajın kendisini imzalayıp şifreleyebilir, WS-ReliableMessaging ile teslim garantisi kurabilirsiniz. Bunlar REST tarafında kutudan çıkmayan, kendinizin inşa etmesi gereken şeyler.

Güncel bir uyarı: JAX-WS bir zamanlar JDK ile birlikte geliyordu, ancak Java SE 11 ile birlikte Java EE modülleri JDK’dan çıkarıldı. Bugün JAX-WS kullanacaksanız bağımlılığı projenize açıkça eklemeniz gerekiyor.

İşin merkezinde WSDL var. Servisiniz hangi metotları sunuyor, hangi tipleri alıyor ve dönüyor; hepsi bu XML belgesinde tarif edilir. İki yönde de çalışır: elinizdeki Java arayüzünden WSDL üretebilir (code-first), ya da size verilen bir WSDL’den wsimport ile Java sınıflarını üretebilirsiniz (contract-first). Karşı taraf size sözleşmeyi dayatıyorsa ikinci yolu kullanırsınız.

Örnek: E-Ticaret Platformu

Aynı e-ticaret senaryosunu bir de SOAP tarafında kuralım ki iki yaklaşım yan yana görünsün.

1. Ürünleri Listeleme

Ürün listeleme için bir ProductCatalog servisi tanımlıyoruz. Burada adres ya da HTTP metodu belirtmiyoruz; yalnızca hangi metotların dışarıya açılacağını söylüyoruz.

java
import javax.jws.WebMethod;import javax.jws.WebService;import java.util.List; @WebServicepublic interface ProductCatalog {    @WebMethod    List<Product> getAllProducts();}
java
import javax.jws.WebService;import java.util.List; @WebService(endpointInterface = "ProductCatalog")public class ProductCatalogImpl implements ProductCatalog {     // Örnek veritabanı bağlantısı    private ProductDatabase productDatabase;     public ProductCatalogImpl() {        this.productDatabase = new ProductDatabase();    }     public List<Product> getAllProducts() {        // Ürünleri veritabanından çek ve döndür        return productDatabase.getAllProducts();    }}
java
import javax.xml.bind.annotation.XmlRootElement; public class Product {    private int id;    private String name;    private double price;     // Getter ve Setter metotları}
java
import java.util.ArrayList;import java.util.List; public class ProductDatabase {    public List<Product> getAllProducts() {        // Gerçekleştirilecek işlemler        // Örnek: Veritabanından tüm ürünleri al ve döndür        return new ArrayList<>(); // Örnek olarak boş bir liste döndürüldü    }}

2. Sipariş Verme

java
import javax.jws.WebMethod;import javax.jws.WebService; @WebServicepublic interface OrderService {    @WebMethod    Order placeOrder(Order newOrder);}
java
import javax.jws.WebService; @WebService(endpointInterface = "OrderService")public class OrderServiceImpl implements OrderService {     // Örnek veritabanı bağlantısı    private OrderDatabase orderDatabase;     public OrderServiceImpl() {        this.orderDatabase = new OrderDatabase();    }     public Order placeOrder(Order newOrder) {        // Yeni siparişi işle ve onayla, ardından oluşturulan siparişi döndür        return orderDatabase.processOrder(newOrder);    }}
java
import javax.xml.bind.annotation.XmlRootElement; public class Order {    private int orderId;    private int productId;    private int quantity;     // Getter ve Setter metotları}
java
public class OrderDatabase {    public Order processOrder(Order newOrder) {        // Gerçekleştirilecek işlemler        // Örnek: Yeni siparişi işle ve onayla, ardından oluşturulan siparişi döndür        return new Order(); // Örnek olarak boş bir sipariş döndürüldü    }}

Yukarıdaki kodda dört parça var: iki arayüz, onların uygulamaları ve taşınan veri sınıfları. Bu ayrım JAX-WS’in çalışma biçiminin doğrudan sonucu.

Arayüzler sözleşmedir. @WebService anotasyonu, bu arayüzün dışarıya açılacağını bildirir; @WebMethod ise hangi metotların yayımlanacağını işaretler. WSDL belgesi de tam olarak bu arayüzlerden üretilir.

Uygulama sınıfları ise işi yapan taraf. @WebService(endpointInterface = "...") ile hangi sözleşmeyi karşıladıklarını söylerler. Sözleşmenin ayrı, uygulamanın ayrı durması sayesinde iş mantığını değiştirseniz bile dışarıya verdiğiniz söz bozulmaz.

Product ve Order ise ağ üzerinde gidip gelen veri taşıyıcıları. @XmlRootElement anotasyonu bunların XML’e çevrilebileceğini belirtir. Dönüşümü yapan da aslında JAX-WS değil, arka plandaki JAXB’dir.

Java EE nedir?

Buraya kadar birkaç kez Java EE dedim. Bu terimin bugün ne anlama geldiğine bakalım, çünkü adı değişti.

Java EE, kurumsal uygulamalarda tekrar tekrar ihtiyaç duyulan işleri standartlaştıran bir spesifikasyon kümesi. Veri tabanı erişimi, işlem yönetimi, mesajlaşma, güvenlik ve web servisleri gibi konuları her projede sıfırdan çözmek yerine hazır sözleşmelere bağlar.

Burada önemli bir güncelleme var. Oracle 2017’de platformu Eclipse Foundation’a devretti ve isim 2018’de Jakarta EE olarak değişti. Marka değişikliğinden ibaret de kalmadı: Jakarta EE 9 ile birlikte bütün paket adları javax.* önekinden jakarta.* önekine taşındı. Yani javax.ws.rs.GET bugün jakarta.ws.rs.GET oluyor. Eski bir öğreticiden kopyaladığınız kod derlenmiyorsa sebebi büyük ihtimalle budur. JAX-RS artık resmi olarak Jakarta RESTful Web Services, JAX-WS ise Jakarta XML Web Services adını taşıyor; kısaltmalar konuşma dilinde yaşamaya devam ediyor. Platformun sunduklarına gelirsek:

Ölçeklenebilirlik: Uygulama sunucusu havuz yönetimi, işlem sınırları ve eşzamanlılık gibi konuları üstlenir, siz iş mantığına odaklanırsınız.

Dayanıklılık: İşlem yönetimi ve hata toparlama davranışları spesifikasyonla tanımlıdır, sunucudan sunucuya değişmez.

Geniş kapsam: Veri tabanı erişiminden mesajlaşmaya, güvenlikten web servislerine kadar çoğu ihtiyacın karşılığı platformda tanımlı.

Java EE'nin içerdiği başlıca bileşenler şunlardır:

Servlets ve JSP: Web uygulamalarının geliştirilmesinde kullanılan temel teknolojilerdir.

EJB (Enterprise JavaBeans): Dağıtık iş mantığını geliştirmek için kullanılır.

JPA (Java Persistence API): Veritabanı işlemlerini kolaylaştıran bir API'dir.

JMS (Java Message Service): Farklı uygulamalar arasında mesaj alışverişi sağlar.

Ve tabii JAX-WS ve JAX-RS: Web servislerinin geliştirilmesi için kullanılan API'lerdir, bu yazının da ana konusu.

Sonuç

Seçim aslında zor değil. Yeni bir servis yazıyorsanız ve karşı taraf size bir şey dayatmıyorsa JAX-RS tarafındasınız: daha az kod, daha az bağımlılık, JSON ile doğal uyum. JAX-WS’i tercih etmenizi gerektiren üç durum var. Karşı taraf size bir WSDL verip "buna uy" diyorsa, mesajın kendisinin imzalanması ya da şifrelenmesi gerekiyorsa, ya da bakımını üstlendiğiniz sistem zaten SOAP konuşuyorsa. Bunların dışında SOAP’ın getirdiği ağırlık karşılığını vermez. Ve hangisini seçerseniz seçin, bugün başlarken paket adının jakarta.* olduğunu unutmayın.

Bu yazımı beğendiyseniz diğer yazılarıma da göz atmanızı öneririm. Bir başka yazıda görüşmek üzere, hoşça kalın. 🚀

Referanslar

Burke, B. (2009). RESTful Java with JAX-RS.

The Java API for RESTful Web Services (JAX-RS) - Rapidly Build Lightweight Web Services, OracleCreating a Simple Web Service and Client with JAX-WS, OracleCreating a RESTful Root Resource Class, Oracle

Share this post

Link copied!
Mustafa Kürşad Başer
Author

Mustafa Kürşad Başer

Senior Software Engineer

A passionate software engineer who enjoys creating elegant solutions to complex problems. Beyond coding, I am deeply interested in exploring the intersections of technology, art, and human consciousness.