Apache CXF dengan WSDL First

Aplikasi CXF-POJO yang telah Anda kembangkan menghasilkan hubungan yang sangat erat antara klien dan server. Memberikan akses langsung ke antarmuka layanan juga dapat menimbulkan ancaman keamanan yang parah. Jadi, pemisahan antara klien dan server biasanya diinginkan, yang dicapai dengan menggunakan WSDL (Bahasa Deskripsi Layanan Web).

Kami menulis antarmuka layanan web dalam dokumen WSDL yang berbasis XML. Kami akan menggunakan alat untuk memetakan WSDL ini ke antarmuka Apache CXF yang kemudian diimplementasikan dan digunakan oleh aplikasi klien dan server kami. Untuk menyediakan decoupling, memulai dengan WSDL adalah cara yang lebih disukai. Untuk ini, Anda perlu mempelajari bahasa baru - WSDL. Penulisan WSDL membutuhkan pendekatan yang cermat dan akan lebih baik jika Anda dapat memperoleh pemahaman tentang ini sebelum Anda mulai mengerjakannya.

Dalam pelajaran ini, kita akan mulai dengan mendefinisikan antarmuka layanan web dalam dokumen WSDL. Kita akan belajar bagaimana menggunakan CXF untuk membuat aplikasi server dan klien dimulai dengan WSDL. Kami akan menjaga aplikasi tetap sederhana untuk menjaga fokus pada penggunaan CXF. Setelah aplikasi server dibuat, kami akan menerbitkannya ke URL yang diinginkan menggunakan kelas CXF bawaan.

Pertama, mari kita jelaskan WSDL yang akan kita gunakan.

WSDL untuk HelloWorld

Layanan web yang akan kita terapkan akan memiliki satu metode web yang disebut greetings yang menerima a stringparameter yang menahan nama pengguna dan mengembalikan pesan string ke pemanggil setelah menambahkan pesan salam ke nama pengguna. Wsdl lengkap ditunjukkan di bawah ini -

//Hello.wsdl
<?xml version = "1.0" encoding = "UTF-8"?>
<wsdl:definitions xmlns:soap = "http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:tns = "http://helloworld.tutorialspoint.com/"
   xmlns:wsdl = "http://schemas.xmlsoap.org/wsdl/"
   xmlns:xsd = "http://www.w3.org/2001/XMLSchema"
   name = "HelloWorld"
   targetNamespace = "http://helloworld.tutorialspoint.com/">
   <wsdl:types>
      <xsd:schema attributeFormDefault = "unqualified"
         elementFormDefault = "qualified"
         targetNamespace = "http://helloworld.tutorialspoint.com/">
         <xsd:element name = "greetings" type = "tns:greetings"/>
         <xsd:complexType name = "greetings">
            <xsd:sequence>
               <xsd:element minOccurs = "0" name = "arg0" type = "xsd:string"/>
            </xsd:sequence>
         </xsd:complexType>
         <xsd:element name = "greetingsResponse"
         type = "tns:greetingsResponse"/>
         <xsd:complexType name = "greetingsResponse">
            <xsd:sequence>
               <xsd:element minOccurs = "0" name = "return" type = "xsd:string"/>
            </xsd:sequence>
         </xsd:complexType>
      </xsd:schema>
   </wsdl:types>
   <wsdl:message name = "greetings">
      <wsdl:part element = "tns:greetings" name = "parameters"> </wsdl:part>
   </wsdl:message>
   <wsdl:message name = "greetingsResponse">
      <wsdl:part element = "tns:greetingsResponse" name = "parameters"> </wsdl:part>
   </wsdl:message>
   <wsdl:portType name = "HelloWorldPortType">
      <wsdl:operation name = "greetings">
         <wsdl:input message = "tns:greetings" name = "greetings">  </wsdl:input>
         <wsdl:output message = "tns:greetingsResponse" name = "greetingsResponse">
         </wsdl:output>
      </wsdl:operation>
   </wsdl:portType>
   <wsdl:binding name = "HelloWorldSoapBinding" type = "tns:HelloWorldPortType">
      <soap:binding style = "document"
      transport = "http://schemas.xmlsoap.org/soap/http"/>
      <wsdl:operation name = "greetings">
         <soap:operation soapAction = "" style = "document"/>
         <wsdl:input name = "greetings"></wsdl:input>
         <wsdl:output name = "greetingsResponse">
            <soap:body use = "literal"/>
         </wsdl:output>
         </wsdl:operation>
   </wsdl:binding>
   <wsdl:service name = "HelloWorldService">
      <wsdl:port binding = "tns:HelloWorldSoapBinding" name = "HelloWorldPort">
         <soap:address location = "http://localhost:9090/HelloServerPort"/>
      </wsdl:port>
   </wsdl:service>
</wsdl:definitions>

Perhatikan bahwa menulis wsdl yang benar secara sintaksis selalu menjadi tantangan bagi para pengembang; ada banyak alat dan editor online tersedia untuk membuat wsdl. Editor ini meminta nama pesan yang ingin Anda terapkan bersama dengan parameter yang ingin Anda sampaikan dalam pesan dan jenis pesan balasan yang Anda ingin aplikasi klien Anda terima. Jika Anda mengetahui sintaks wsdl, Anda dapat memberikan kode untuk seluruh dokumen atau menggunakan salah satu editor untuk membuatnya sendiri.

Dalam wsdl di atas, kami telah mendefinisikan satu pesan yang disebut greetings. Pesan tersebut dikirim ke layanan yang disebutHelloWorldService yang dijalankan pada http://localhost:9090/HelloServerPort.

Dengan ini, sekarang kita akan melanjutkan ke pengembangan server. Sebelum mengembangkan server, kita perlu membuat antarmuka Apache CXF ke layanan web kita. Ini harus dilakukan dari wsdl yang diberikan. Untuk melakukan ini, Anda menggunakan alat yang disebutwsdl2java.

Plugin wsdl2java

Karena kita akan menggunakan maven untuk membangun proyek, Anda perlu menambahkan plugin berikut ke pom.xml mengajukan.

<plugins>
   <plugin>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-codegen-plugin</artifactId>
      <version>3.3.0</version>
      <executions>
         <execution>
            <id>generate-sources</id>
            <phase>generate-sources</phase>
            <configuration>
               <wsdlOptions>
                  <wsdlOption>
                     <wsdl>src/main/resources/hello.wsdl</wsdl>
                     <faultSerialVersionUID> 1 </faultSerialVersionUID>
                  </wsdlOption>
               </wsdlOptions>
            </configuration>
            <goals>
               <goal>wsdl2java</goal>
            </goals>
         </execution>
      </executions>
   </plugin>
</plugins>

Perhatikan bahwa kami menentukan lokasi file wsdl mengajukan sebagai src/main/resources/Hello.wsdl. Anda harus memastikan bahwa Anda membuat struktur direktori yang sesuai untuk proyek Anda dan menambahkan yang ditunjukkan sebelumnyahello.wsdl file ke folder tertentu.

Itu wsdl2javaplugin akan mengkompilasi wsdl ini dan membuat kelas Apache CXF di folder yang telah ditentukan sebelumnya. Struktur proyek lengkap ditampilkan di sini untuk referensi siap Anda.

Sekarang, Anda siap membuat server menggunakan wsdl2javakelas yang dihasilkan. Kelas-kelas yang telah dibuat wsdl2java ditunjukkan pada gambar di bawah ini -

Antarmuka Layanan yang Dihasilkan

Dalam daftar kelas yang dihasilkan, Anda pasti telah memperhatikan salah satunya adalah antarmuka Apache CXF - ini HelloWorldPortType.java. Periksa file ini di editor kode Anda. Isi file ditampilkan di sini untuk referensi siap Anda -

//HelloWorldPortType.java
package com.tutorialspoint.helloworld;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
/**
* This class was generated by Apache CXF 3.3.0
* 2019-02-11T12:05:55.220+05:30
* Generated source version: 3.3.0
*
*/

@WebService(targetNamespace = "http://helloworld.tutorialspoint.com/",
   name = "HelloWorldPortType")
@XmlSeeAlso({ObjectFactory.class})
public interface HelloWorldPortType {
   @WebMethod
   @RequestWrapper(localName = "greetings", targetNamespace =
      "http://helloworld.tutorialspoint.com/", className =
      "com.tutorialspoint.helloworld.Greetings")
      @ResponseWrapper(localName = "greetingsResponse", targetNamespace =
         "http://helloworld.tutorialspoint.com/", className =
         "com.tutorialspoint.helloworld.GreetingsResponse")
   @WebResult(name = "return", targetNamespace =
      "http://helloworld.tutorialspoint.com/")
   public java.lang.String greetings(
      @WebParam(name = "arg0", targetNamespace =
      "http://helloworld.tutorialspoint.com/")
      java.lang.String arg0
   );
}

Perhatikan bahwa antarmuka berisi metode yang disebut greetings. Ini adalah jenis pesan di wsdl kami. Ituwsdl2javaalat telah menambahkan metode ini ke antarmuka yang dihasilkan. Sekarang, Anda dapat memahami bahwa pesan apa pun yang Anda tulis di wsdl Anda, metode yang sesuai akan dibuat di antarmuka.

Sekarang, tugas Anda adalah mengimplementasikan semua metode ini sesuai dengan berbagai pesan yang telah Anda tentukan di wsdl Anda. Perhatikan bahwa dalam contoh Apache CXF-First sebelumnya, kami memulai dengan antarmuka Apache CXF untuk layanan web kami. Dalam hal ini, antarmuka Apache CXF dibuat dari wsdl.

Menerapkan Antarmuka Layanan

Implementasi antarmuka layanan itu sepele. Implementasi lengkapnya ditunjukkan pada daftar di bawah ini -

//HelloWorldImpl.java
package com.tutorialspoint.helloworld;
public class HelloWorldImpl implements HelloWorldPortType {
   @Override
   public String greetings(String name) {
      return ("hi " + name);
   }
}

Kode tersebut mengimplementasikan metode antarmuka tunggal yang dipanggil greetings. Metode ini mengambil satu parameterstring type, menambahkan pesan "hi" padanya dan mengembalikan string yang dihasilkan ke pemanggil.

Selanjutnya kita akan menulis aplikasi server.

Mengembangkan Server

Mengembangkan aplikasi server sekali lagi tidak penting. Di sini, kami akan menggunakan CXF yang disediakanEndpointkelas untuk mempublikasikan layanan kami. Ini dilakukan dalam dua baris kode berikut -

HelloWorldPortType implementor = new HelloWorldImpl();
   Endpoint.publish("http://localhost:9090/HelloServerPort",
      implementor,
      new LoggingFeature());

Pertama, kami membuat objek kelas pelaksana layanan kami - HelloWorldImpl. Kemudian, kami meneruskan referensi ini sebagai parameter kedua kepublishmetode. Parameter pertama adalah alamat yang menerbitkan layanan - klien akan menggunakan URL ini untuk mengakses layanan. Seluruh sumber untuk aplikasi server diberikan di sini -

//Server.java
package com.tutorialspoint.helloworld;
import javax.xml.ws.Endpoint;
import org.apache.cxf.ext.logging.LoggingFeature;
public class Server {
   public static void main(String[] args) throws Exception {
      HelloWorldPortType implementor = new HelloWorldImpl();
      Endpoint.publish("http://localhost:9090/HelloServerPort",
         implementor,
         new LoggingFeature());
      System.out.println("Server ready...");
      Thread.sleep(5 * 60 * 1000);
      System.out.println("Server exiting");
      System.exit(0);
   }
}

Untuk membangun kelas server ini, Anda perlu menambahkan profil build di file pom.xml. Ini ditunjukkan di bawah -

<profile>
   <id>server</id>
   <build>
      <defaultGoal>test</defaultGoal>
      <plugins>
         <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.6.0</version>
            <executions>
               <execution>
                  <phase>test</phase>
                  <goals>
                     <goal>java</goal>
                  </goals>
                  <configuration>
                     <mainClass>
                        com.tutorialspoint.helloworld.Server
                     </mainClass>
                  </configuration>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </build>
   <dependencies>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http-jetty</artifactId>
         <version>3.3.0</version>
      </dependency>
   </dependencies>
</profile>

Perhatikan bahwa nama sepenuhnya memenuhi syarat Serverkelas ditentukan dalam konfigurasi. Selain itu, tag ketergantungan menentukan bahwa kami akan menggunakan server web embedded jetty untuk menyebarkan aplikasi server kami.

Menerapkan Server

Terakhir, untuk menerapkan aplikasi server, Anda perlu membuat satu modifikasi lagi di pom.xml untuk menyiapkan aplikasi Anda sebagai aplikasi web. Kode yang perlu Anda tambahkan ke filepom.xml diberikan di bawah -

<defaultGoal>install</defaultGoal>
<pluginManagement>
   <plugins>
      <plugin>
         <artifactId>maven-war-plugin</artifactId>
         <version>3.2.2</version>
         <configuration>
            <webXml>src/main/webapp/WEB-INF/web.xml</webXml>
            <webResources>
               <resource>
                  <directory>src/main/resources</directory>
                  <targetPath>WEB-INF</targetPath>
                  <includes>
                     <include>*.wsdl</include>
                  </includes>
               </resource>
            </webResources>
         </configuration>
      </plugin>
   </plugins>
</pluginManagement>

Sebelum Anda menerapkan aplikasi, Anda perlu menambahkan dua file lagi ke proyek Anda. Ini ditunjukkan pada gambar di bawah -

File-file ini adalah file standar CXF yang mendefinisikan pemetaan CXFServlet. Kode di dalamweb.xml file ditampilkan di sini untuk referensi cepat Anda -

//cxf-servlet.xml
<web-app xmlns = "http://java.sun.com/xml/ns/javaee"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" version="2.5"
   xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee
   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
   <display-name>cxf</display-name>
   <servlet>
      <description>Apache CXF Endpoint</description>
      <display-name>cxf</display-name>
      <servlet-name>cxf</servlet-name>
      <servlet-class>
         org.apache.cxf.transport.servlet.CXFServlet
      </servlet-class>
      <load-on-startup>1</load-on-startup>
   </servlet>
   <servlet-mapping>
      <servlet-name>cxf</servlet-name>
      <url-pattern>/services/*</url-pattern>
   </servlet-mapping>
   <session-config>
      <session-timeout>60</session-timeout>
   </session-config>
</web-app>

Dalam cxf-servlet.xmlAnda mendeklarasikan properti untuk titik akhir layanan Anda. Ini ditunjukkan pada potongan kode di bawah ini -

<beans ...>
   <jaxws:endpoint xmlns:helloworld = "http://tutorialspoint.com/"
      id="helloHTTP"
      address = "http://localhost:9090/HelloServerPort"
      serviceName = "helloworld:HelloServiceService"
      endpointName = "helloworld:HelloServicePort">
   </jaxws:endpoint>
</beans>

Di sini kita mendefinisikan id untuk titik akhir layanan kita, alamat di mana layanan akan tersedia, nama layanan dan nama titik akhir. Sekarang, Anda memahami bagaimana layanan Anda dirutekan dan diproses oleh servlet CXF.

Akhir pom.xml

Itu pom.xmlmenyertakan beberapa dependensi lagi. Daripada menjelaskan semua dependensi, kami telah menyertakan versi terakhir pom.xml di bawah -

<?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>com.tutorialspoint</groupId>
   <artifactId>cxf-wsdl</artifactId>
   <version>1.0</version>
   <packaging>jar</packaging>
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
   </properties>
   <build>
      <defaultGoal>install</defaultGoal>
      <pluginManagement>
         <plugins>
            <plugin>
               <artifactId>maven-war-plugin</artifactId>
               <version>3.2.2</version>
               <configuration>
                  <webXml>src/main/webapp/WEB-INF/web.xml</webXml>
                  <webResources>
                     <resource>
                        <directory>src/main/resources</directory>
                        <targetPath>WEB-INF</targetPath>
                        <includes>
                           <include>*.wsdl</include>
                        </includes>
                     </resource>
                  </webResources>
               </configuration>
            </plugin>
         </plugins>
      </pluginManagement>
      <plugins>
         <plugin>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-codegen-plugin</artifactId>
            <version>3.3.0</version>
            <executions>
               <execution>
                  <id>generate-sources</id>
                  <phase>generate-sources</phase>
                  <configuration>
                     <wsdlOptions>
                        <wsdlOption>
                           <wsdl>src/main/resources/Hello.wsdl</wsdl>
                           <faultSerialVersionUID>1</faultSerialVersionUID>
                        </wsdlOption>
                     </wsdlOptions>
                  </configuration>
                  <goals>
                     <goal>wsdl2java</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </build>
   <profiles>
      <profile>
         <id>server</id>
         <build>
            <defaultGoal>test</defaultGoal>
            <plugins>
               <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <version>1.6.0</version>
                  <executions>
                     <execution>
                        <phase>test</phase>
                        <goals>
                           <goal>java</goal>
                        </goals>
                        <configuration>
                           <mainClass>
                              com.tutorialspoint.helloworld.Server
                           </mainClass>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
         <dependencies>
            <dependency>
               <groupId>org.apache.cxf</groupId>
               <artifactId>cxf-rt-transports-http-jetty</artifactId>
               <version>3.3.0</version>
            </dependency>
         </dependencies>
      </profile>
      <profile>
         <id>client</id>
         <build>
            <defaultGoal>test</defaultGoal>
            <plugins>
               <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <executions>
                     <execution>
                        <phase>test</phase>
                        <goals>
                           <goal>java</goal>
                        </goals>
                        <configuration>
                           <mainClass>
                              com.tutorialspoint.helloworld.Client
                           </mainClass>
                        </configuration>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
      </profile>
   </profiles>
   <dependencies>
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-frontend-jaxws</artifactId>
         <version>3.3.0</version>
      </dependency>
     
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http</artifactId>
         <version>3.3.0</version>
      </dependency>
      
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-management</artifactId>
         <version>3.3.0</version>
      </dependency>
      
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-features-metrics</artifactId>
         <version>3.3.0</version>
      </dependency>
      
      <dependency>
         <groupId>org.apache.cxf.xjc-utils</groupId>
         <artifactId>cxf-xjc-runtime</artifactId>
         <version>3.3.0</version>
      </dependency>
      
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-features-logging</artifactId>
         <version>3.3.0</version>
      </dependency>
     
     <dependency>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>exec-maven-plugin</artifactId>
         <version>1.6.0</version>
      </dependency>
      
      <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-api</artifactId>
         <version>1.8.0-beta2</version>
      </dependency>
      
      <dependency>
         <groupId>org.apache.cxf</groupId>
         <artifactId>cxf-rt-transports-http-jetty</artifactId>
         <version>3.3.0</version>
      </dependency>
   </dependencies>
</project>

Perhatikan bahwa itu juga termasuk profil untuk membangun klien yang akan kita pelajari segera di bagian selanjutnya.

Menjalankan Layanan HelloWorld

Sekarang, Anda siap menjalankan aplikasi web. Di jendela perintah, jalankan skrip build menggunakan perintah berikut.

mvn clean install

Ini akan menghasilkan kelas Apache CXF yang sesuai dari wsdl Anda, mengkompilasi kelas Apache CXF Anda, menerapkan server pada server jetty tertanam dan menjalankan aplikasi Anda.

Anda akan melihat pesan berikut di konsol -

INFO: Setting the server's publish address to be 
http://localhost:9090/HelloServerPort
Server ready...

Seperti sebelumnya, Anda dapat menguji server dengan membuka URL server di browser Anda.

Karena kami tidak menentukan operasi apa pun, hanya pesan kesalahan yang dikembalikan ke browser oleh aplikasi kami. Sekarang, coba tambahkan?wsdl ke URL Anda dan Anda akan melihat output berikut -

Jadi aplikasi server kita berjalan seperti yang diharapkan. Anda dapat menggunakan SOAP Client sepertiPostman dijelaskan sebelumnya untuk menguji layanan Anda lebih lanjut.

Bagian selanjutnya dari tutorial ini adalah menulis klien yang menggunakan layanan kami.

Mengembangkan Klien

Menulis klien dalam aplikasi CXF sama pentingnya dengan menulis server. Berikut adalah kode lengkap untuk klien yang intinya hanya terdiri dari tiga baris, baris selebihnya hanya mencetak informasi layanan kepada pengguna.

//Client.java
package com.tutorialspoint.helloworld;
public class Client {
   public static void main(String[] args) throws Exception {
      //Create the service client with its default wsdlurl
      HelloWorldService helloServiceService = new HelloWorldService();
      System.out.println("service: " +
         helloServiceService.getServiceName());
      System.out.println("wsdl location: " +
         helloServiceService.getWSDLDocumentLocation());
      HelloWorldPortType helloService =
         helloServiceService.getHelloWorldPort();
      System.out.println(helloService.greetings
      (System.getProperty("user.name")));
   }
}

Di sini, kami hanya membuat contoh layanan kami HelloWorldService, dapatkan portnya dengan menelepon getHelloWorldPort metode, dan kemudian lulus greetingspesan untuk itu. Jalankan klien dan Anda akan melihat output berikut -

service: {http://helloworld.tutorialspoint.com/}HelloWorldService
wsdl location: file:/Users/drsarang/Desktop/tutorialpoint/cxf-
wsdl/src/main/resources/Hello.wsdl
hi drsarang

Sejauh ini Anda telah mempelajari cara menggunakan CXF dengan arsitektur Apache CXF-First dan WSDL-First. Dalam pendekatan Apache CXF-First, Anda menggunakan POJO denganServerFactoryBeankelas dari perpustakaan CXF untuk membuat server. Untuk membuat klien yang Anda gunakanClientProxyFactoryBeankelas dari perpustakaan CXF. Dalam pendekatan WSDL-First, Anda menggunakanEndpointkelas untuk mempublikasikan layanan di URL yang diinginkan dan pelaksana tertentu. Sekarang Anda dapat memperluas teknik ini untuk mengintegrasikan protokol dan transport yang berbeda.