28.2. 소비자 구현
28.2.1. 개요
WSDL 계약에서 시작할 때 소비자를 구현하려면 다음 스텁을 사용해야 합니다.
- 서비스 클래스
- SEI
이러한 스텁을 사용하여 소비자 코드는 서비스 프록시를 인스턴스화하여 원격 서비스에 요청합니다. 또한 소비자의 비즈니스 논리를 구현합니다.
28.2.2. 생성된 서비스 클래스
예 28.2. “생성된 서비스 클래스 개요” 생성된 서비스 클래스의 일반적인 개요를 보여줍니다, ServiceName_Service
[2]javax.xml.ws.Service
기본 클래스를 확장하는 .
예 28.2. 생성된 서비스 클래스 개요
@WebServiceClient(name="..." targetNamespace="..." wsdlLocation="...") public class ServiceName extends javax.xml.ws.Service { ... public ServiceName(URL wsdlLocation, QName serviceName) { } public ServiceName() { } // Available only if you specify '-fe cxf' option in wsdl2java public ServiceName(Bus bus) { } @WebEndpoint(name="...") public SEI getPortName() { } . . . }
예 28.2. “생성된 서비스 클래스 개요” 의 ServiceName
클래스는 다음 메서드를 정의합니다.
-
ServiceName
(URL wsdlLocation, QName serviceName) -wsdl:service
요소에 따라 wsdlLocation 서비스에서 얻을 수 있는 WSDL 계약과 함께 서비스 오브젝트를 구성합니다. -
ServiceName()
- 기본 생성자입니다. 스텁 코드가 생성된 시간(예:wsdl2java
툴을 실행하는 경우)에 제공된 서비스 이름 및 WSDL 계약을 기반으로 서비스 개체를 구성합니다. 이 생성자를 사용하면 WSDL 계약이 지정된 위치에서 계속 사용 가능함을 전제로 합니다. -
ServiceName(Bus bus)
- (CXF 특정) 서비스를 구성하는 데 사용되는 버스 인스턴스를 지정할 수 있는 추가 생성자입니다. 이 기능은 다중 버스 인스턴스를 서로 다른 스레드와 연결할 수 있는 다중 스레드 애플리케이션의 컨텍스트에서 유용할 수 있습니다. 이 생성자는 사용자가 지정하는 버스가 이 서비스에 사용되는지 확인하는 간단한 방법을 제공합니다.wsdl2java
툴을 호출할 때-fe cxf
옵션을 지정하는 경우에만 사용 가능합니다. -
getPortName()
- PortName 과 같은name
속성이 있는wsdl:port
요소에서 정의한 엔드포인트에 대한 프록시를 반환합니다. getter 메서드는 ServiceName 서비스에서 정의한 모든wsdl:port
요소에 대해 생성됩니다. 여러 끝점 정의가 포함된wsdl:service
요소에는 여러getPortName()
메서드가 있는 생성된 서비스 클래스가 생성됩니다.
28.2.3. 서비스 엔드 포인트 인터페이스
원래의 WSDL 계약에 정의된 모든 인터페이스의 경우 해당 SEI를 생성할 수 있습니다. 서비스 엔드포인트 인터페이스는 wsdl:portType
요소의 Java 매핑입니다. 원래 wsdl:portType
요소에 정의된 각 작업은 SEI의 해당 메서드에 매핑됩니다. 작업의 매개변수는 다음과 같이 매핑됩니다. . 입력 매개변수는 메서드 인수에 매핑됩니다.
- 첫 번째 출력 매개 변수는 반환 값에 매핑됩니다.
-
출력 매개 변수가 두 개 이상 있는 경우 두 번째 및 후속 출력 매개 변수는 메서드 인수에 매핑됩니다(더 이상 이러한 인수의 값은 holder 유형을 사용하여 전달해야 함).
예를 들어 예 28.3. “Greeter Service Endpoint Interface” 은 예 26.1. “helloworld WSDL 계약” 에 정의된 wsdl:portType
요소에서 생성된 Greeter SEI를 표시합니다. 간단히 하기 위해 예 28.3. “Greeter Service Endpoint Interface” 는 표준 JAXB 및 JAX-WS 주석을 생략합니다.
예 28.3. Greeter Service Endpoint Interface
package org.apache.hello_world_soap_http; ... public interface Greeter { public String sayHi(); public String greetMe(String requestType); public void greetMeOneWay(String requestType); public void pingMe() throws PingMeFault; }
28.2.4. 소비자 주요 기능
예 28.4. “소비자 구현 코드” HelloWorld 소비자를 구현하는 코드를 보여줍니다. 소비자는 SOAPService 서비스의 SoapPort 포트에 연결한 다음 Greeter 포트 유형에서 지원하는 각 작업을 계속 호출합니다.
예 28.4. 소비자 구현 코드
package demo.hw.client; import java.io.File; import java.net.URL; import javax.xml.namespace.QName; import org.apache.hello_world_soap_http.Greeter; import org.apache.hello_world_soap_http.PingMeFault; import org.apache.hello_world_soap_http.SOAPService; public final class Client { private static final QName SERVICE_NAME = new QName("http://apache.org/hello_world_soap_http", "SOAPService"); private Client() { } public static void main(String args[]) throws Exception { if (args.length == 0) { System.out.println("please specify wsdl"); System.exit(1); } URL wsdlURL; File wsdlFile = new File(args[0]); if (wsdlFile.exists()) { wsdlURL = wsdlFile.toURL(); } else { wsdlURL = new URL(args[0]); } System.out.println(wsdlURL); SOAPService ss = new SOAPService(wsdlURL,SERVICE_NAME); Greeter port = ss.getSoapPort(); String resp; System.out.println("Invoking sayHi..."); resp = port.sayHi(); System.out.println("Server responded with: " + resp); System.out.println(); System.out.println("Invoking greetMe..."); resp = port.greetMe(System.getProperty("user.name")); System.out.println("Server responded with: " + resp); System.out.println(); System.out.println("Invoking greetMeOneWay..."); port.greetMeOneWay(System.getProperty("user.name")); System.out.println("No response from server as method is OneWay"); System.out.println(); try { System.out.println("Invoking pingMe, expecting exception..."); port.pingMe(); } catch (PingMeFault ex) { System.out.println("Expected exception: PingMeFault has occurred."); System.out.println(ex.toString()); } System.exit(0); } }
예 28.4. “소비자 구현 코드” 의 client.main()
방법은 다음과 같이 진행됩니다.
Apache CXF 런타임 클래스가 클래스 경로에 있는 경우 런타임은 암시적으로 초기화됩니다. Apache CXF를 초기화하기 위해 특수 함수를 호출할 필요가 없습니다.
소비자는 HelloWorld에 대한 WSDL 계약의 위치를 제공하는 단일 문자열 인수가 필요합니다. WSDL 계약의 위치는 wsdlURL
에 저장됩니다.
WSDL 계약의 위치 및 서비스 이름이 필요한 생성자를 사용하여 서비스 오브젝트를 생성합니다. 적절한 getPortName()
메서드를 호출하여 필요한 포트의 인스턴스를 가져옵니다. 이 경우 SOAPService 서비스는 Greeter
서비스 엔드포인트 인터페이스를 구현하는 SoapPort 포트만 지원합니다.
소비자는 Greeter 서비스 엔드포인트 인터페이스에서 지원하는 각 메서드를 호출합니다.
pingMe()
메서드의 경우 예제 코드는 PingMeFault fault 예외를 catch하는 방법을 보여줍니다.
28.2.5. -fe cxf 옵션으로 생성된 클라이언트 프록시
wsdl2java에서 -fe cxf
옵션을 지정하여 클라이언트 프록시를 생성하는 경우( cxf
frontend를 선택하여) 생성된 클라이언트 프록시 코드가 Java 7과 더 잘 통합됩니다. 이 경우 getServiceNamePort()
메서드를 호출하면 SEI의 하위 인터페이스인 형식을 반환하고 다음과 같은 추가 인터페이스를 구현합니다.
-
java.lang.AutoCloseable
-
javax.xml.ws.BindingProvider
(JAX-WS 2.0) -
org.apache.cxf.endpoint.Client
이를 통해 클라이언트 프록시 작업을 단순화하는 방법을 보려면 표준 JAX-WS 프록시 오브젝트를 사용하여 작성된 다음 Java 코드 샘플을 고려하십시오.
// Programming with standard JAX-WS proxy object // (ServiceNamePortType port = service.getServiceNamePort(); ((BindingProvider)port).getRequestContext() .put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, address); port.serviceMethod(...); ((Closeable)port).close();
또한 cxf
frontend에서 생성된 코드를 사용하여 작성한 다음 동등한 코드 샘플과 위 코드를 비교합니다.
// Programming with proxy generated using '-fe cxf' option // try (ServiceNamePortTypeProxy port = service.getServiceNamePort()) { port.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, address); port.serviceMethod(...); }