Belajar SOAP - Membuat Service SOAP Pertama (Java)
Episode 4 of 23

Belajar SOAP - Membuat Service SOAP Pertama (Java)

Praktik nyata pertama: membangun service SOAP di Java dengan JAX-WS memakai anotasi WebService dan WebMethod, publishing endpoint, menguji dengan curl dan SoapUI, hingga membangkitkan client dari WSDL dengan wsimport dan wsdl2java.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 3 kita memahami kontrak WSDL, sekarang saatnya praktik nyata: membangun service SOAP pertama di Java. Kita memakai JAX-WS (Jakarta XML Web Services) — API standar Java untuk web services — yang sudah menjadi tulang punggung ekosistem SOAP Java selama hampir dua dekade.

Mengapa Java dulu? Karena ekosistem Java (JAX-WS, Metro, Apache CXF, WSS4J) adalah referensi industri untuk SOAP. Di episode berikutnya kita lihat bahasa lain; setelah episode ini, konsep yang sama akan terasa familier di PHP, .NET, dan Python.

Project Setup

Kita pakai Maven untuk mengelola dependensi. Service ini berjalan dengan publish endpoint bawaan JAX-WS, jadi tanpa server aplikasi eksternal:

Inisialisasi project Maven
mkdir -p soap-lab/bank-service && cd soap-lab/bank-service
mvn archetype:generate -DgroupId=id.devnull.soap \
  -DartifactId=bank-service -DarchetypeArtifactId=maven-archetype-quickstart

Tambahkan dependensi Jakarta XML Web Services ke pom.xml:

pom.xml
<dependencies>
  <dependency>
    <groupId>jakarta.xml.ws</groupId>
    <artifactId>jakarta.xml.ws-api</artifactId>
    <version>4.0.2</version>
  </dependency>
  <dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-ri</artifactId>
    <version>4.0.2</version>
  </dependency>
</dependencies>

Versi 4.0.x adalah rilis Jakarta EE yang kompatibel dengan JDK 17+ — versi inilah yang dipakai pada contoh di series ini.

Anotasi @WebService menandai class sebagai service SOAP; @WebMethod menandai method yang diekspos. Setiap method publik otomatis menjadi operasi WSDL:

JavaBankServiceImpl.java
package id.devnull.soap;
 
import jakarta.jws.WebMethod;
import jakarta.jws.WebParam;
import jakarta.jws.WebService;
import java.math.BigDecimal;
 
@WebService(name = "BankService", targetNamespace = "urn:example:bank")
public class BankService {
 
    @WebMethod
    public BigDecimal getBalance(
            @WebParam(name = "accountNo") String accountNo) {
        if ("ACC-001".equals(accountNo)) {
            return new BigDecimal("2750000.00");
        }
        throw new IllegalArgumentException("Akun tidak ditemukan: " + accountNo);
    }
}

Perhatikan targetNamespace — ini menjadi namespace WSDL dan semua elemen pesan, mengikuti kontrak yang kita tulis di episode 3. Gaya argument document-literal dihasilkan otomatis oleh JAX-WS.

Note

throw IllegalArgumentException akan dipetakan JAX-WS menjadi SOAP Fault. Di episode 8 kita akan menangani pemetaan error bisnis secara eksplisit dengan @WebFault.

Publishing Endpoint

Untuk percobaan cepat, publish endpoint langsung dari main — tanpa Tomcat. JAX-WS menyediakan endpoint publisher bawaan:

JavaMain.java
package id.devnull.soap;
 
import jakarta.xml.ws.Endpoint;
 
public class Main {
    public static void main(String[] args) {
        String url = "http://localhost:8080/bank";
        Endpoint.publish(url, new BankService());
        System.out.println("Service berjalan di " + url + "?wsdl");
    }
}

Jalankan, lalu cek WSDL yang dibangkitkan JAX-WS dari kode (pola code-first):

Jalankan dan cek WSDL
mvn compile exec:java
curl -s http://localhost:8080/bank?wsdl

Jika WSDL muncul, service kalian sudah hidup. Ini contoh perfect untuk memahami pola code-first dari episode 3: kode adalah sumber kebenaran, WSDL di-generate.

Menguji dengan curl

Cara paling jujur menguji service adalah mengirim raw SOAP via curl. Perhatikan namespace SOAP 1.1 yang dipakai JAX-WS default:

Request SOAP via curl
curl -s -X POST http://localhost:8080/bank \
  -H 'Content-Type: text/xml; charset=utf-8' \
  -d '<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:bank="urn:example:bank">
    <soap:Body>
      <bank:getBalance>
        <bank:accountNo>ACC-001</bank:accountNo>
      </bank:getBalance>
    </soap:Body>
  </soap:Envelope>'

Response datang sebagai envelope SOAP dengan elemen getBalanceResponse — persis seperti kontrak di episode 2.

Membangkitkan Client dari WSDL

Keunggulan SOAP: client bisa dibangkitkan langsung dari WSDL. Java menyediakan wsimport (bagian dari JDK, sekarang di bawah jaxws tools) dan CXF menyediakan wsdl2java:

Generate client dengan wsimport
wsimport -d ./target/generated -p id.devnull.soap.client \
  http://localhost:8080/bank?wsdl

Kode client yang dibangkitkan dipakai seperti ini:

JavaClient.java
package id.devnull.soap;
 
import id.devnull.soap.client.BankService;
import id.devnull.soap.client.BankServicePortType;
import java.math.BigDecimal;
 
public class Client {
    public static void main(String[] args) {
        BankService service = new BankService();
        BankServicePortType port = service.getBankPort();
        BigDecimal balance = port.getBalance("ACC-001");
        System.out.println("Saldo: " + balance);
    }
}

Tip

Jika project kalian memakai Apache CXF, gunakan wsdl2java dengan flag -wsdlLocation agar client tetap memakai WSDL jarak jauh saat runtime — berguna untuk testing dan staging. wsimport bawaan JDK lebih sederhana, sedangkan wsdl2java lebih fleksibel.

Common Pitfalls

  • JDK 17+ dan wsimport — tool ini tidak lagi dibundel di JDK baru; install sebagai plugin Maven (jaxws-maven-plugin) atau gunakan wsdl2java dari CXF.
  • Namespace SOAP tak cocok — jika client dibangkitkan dari WSDL SOAP 1.1 tapi kalian mengirim envelope SOAP 1.2, server menolak dengan error "unknown namespace".
  • @WebMethod(exclude = true) — method publik yang tidak ingin diekspos harus diberi anotasi ini; jika tidak, JAX-WS mengeksposnya.
  • Localhost di lingkungan terdistribusisoap:address location memakai hostname/port saat publish; saat deploy lintas host, sesuaikan location atau pakai Tomcat/CXF.

Penutup

Inti yang harus dibawa pulang:

  • JAX-WS memakai anotasi @WebService/@WebMethod; WSDL di-generate otomatis (code-first).
  • Endpoint.publish cukup untuk lab; produksi butuh server aplikasi (Tomcat) atau CXF.
  • Uji dengan curl raw sebelum memakai GUI — membaca envelope mentah adalah skill wajib.
  • wsimport/wsdl2java membangkitkan client langsung dari WSDL — kekuatan kontrak machine-readable.

Di episode 5 selanjutnya kita akan melihat SOAP di PHP, .NET, dan PythonSoapClient/SoapServer bawaan PHP, WCF & dotnet-svcutil di .NET, dan library zeep di Python — lengkap dengan contoh client dan service untuk tiap bahasa. Sampai jumpa di episode 5!

Belajar SOAP - Membuat Service SOAP Pertama (Java) | Belajar SOAP