This is version . It is not the current version, and thus it cannot be edited.
[Back to current version]   [Restore this version]

프로젝트 생성하기#

mvn archetype:create -DarchetypeGroupId=org.springframework.ws \
  -DarchetypeArtifactId=spring-ws-archetype \
  -DarchetypeVersion=1.0.1 \
  -DgroupId=com.mycompany.hr \
  -DartifactId=holidayService

web.xml 파일#

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
             http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
         version="2.4">

    <display-name>MyCompany HR Holiday Service</display-name>

    <!-- take especial notice of the name of this servlet -->
    <servlet>
        <servlet-name>spring-ws</servlet-name>
        <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>spring-ws</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>

[servlet명]-ws-servlet.xml 파일#

이 파일은 EndPoints, WebServiceMessageReceivers 를 정의한다. 여기서 파일명은 openframework-ws-servlet.xml 이라고 가정한다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">


</beans>

Endpoint 구현하기#

XML 메시지를 다루기 위해 Endpoint를 구현해야 한다. 여기서 XML을 다루기 위해 사용할수 있는 방식은 JDOM, DOM, dom4j, XOM, SAX, 그리고 StAX 가 있다.

package openframework.ws;

import java.text.SimpleDateFormat;
import java.util.Date;

import openframework.service.HumanResourceService;

import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.xpath.XPath;
import org.springframework.ws.server.endpoint.AbstractJDomPayloadEndpoint;

public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {

  private XPath startDateExpression;
  private XPath endDateExpression;
  private XPath nameExpression;
  private HumanResourceService humanResourceService;

  public HolidayEndpoint(HumanResourceService humanResourceServicethrows JDOMException {
    this.humanResourceService = humanResourceService;
    Namespace namespace = Namespace.getNamespace("hr""http://openframework.or.kr/hr/schemas");
    startDateExpression = XPath.newInstance("//hr:StartDate");
    startDateExpression.addNamespace(namespace);
    endDateExpression = XPath.newInstance("//hr:EndDate");
    endDateExpression.addNamespace(namespace);
    nameExpression = XPath.newInstance("concat(//hr:FirstName,' ',//hr:LastName)");
    nameExpression.addNamespace(namespace);
  }

  protected Element invokeInternal(Element holidayRequestthrows Exception {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    Date startDate = dateFormat.parse(startDateExpression.valueOf(holidayRequest));
    Date endDate = dateFormat.parse(endDateExpression.valueOf(holidayRequest));
    String name = nameExpression.valueOf(holidayRequest);

    humanResourceService.bookHoliday(startDate, endDate, name);
    return null;
  }
}

openframework-ws-servlet.xml 파일에 다음 설정을 추가한다.

<beans xmlns="http://www.springframework.org/schema/beans">
    <bean id="holidayEndpoint" class="openframework.ws.HolidayEndpoint">
        <constructor-arg ref="hrService"/>
    </bean>

    <bean id="hrService" class="openframework.service.StubHumanResourceService"/>
</beans>

메시지를 Endpoint로 보내기#

<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
    <property name="mappings">
        <props>
            <prop key="{http://openframework.or.kr/hr/schemas}HolidayRequest">holidayEndpoint</prop>
        </props>
    </property>
    <property name="interceptors">
        <bean class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor"/>
    </property>
</bean>

WSDL 배포하기#

<bean id="holiday" class="org.springframework.ws.wsdl.wsdl11.DynamicWsdl11Definition">   
  <property name="builder">
    <bean class="org.springframework.ws.wsdl.wsdl11.builder.XsdBasedSoap11Wsdl4jDefinitionBuilder">
      <property name="schema" value="/WEB-INF/xsd/hr.xsd"/>
      <property name="portTypeName" value="HumanResource"/>
      <property name="locationUri" value="http://localhost:8888/holidayService/"/>
      <property name="targetNamespace" value="http://openframework.or.kr/hr/definitions"/>
    </bean>
  </property>
</bean>

여기서 bean의 id값인 holiday는 wsdl을 가져올때 사용되는 값이다. 간단하게는 http://[서버주소]/[context명]/[bean의 id].wsdl 이라는 URL을 사용하면 WSDL을 가져올수 있다. 위와 같은 경우 다음과 같은 URL을 가지게 된다.

http://localhost:8888/spring-ws/holiday.wsdl

Spring WebService#

Spring WebService의 핵심 인터페이스는 WebServiceMessage이다. SoapMessage는 SOAP관련 WebServiceMessage의 하위클래스이다.

실제 WebServiceMessage를 생성하는 메소드는 WebServiceMessageFactory에 들어있다.

SaajSoapMessageFactory

SOAP with Attachments API for Java를 사용한다.

<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory" />

<div class="information"> SAAJ는 DOM에 기초한다. 이 말은 메모리에 저장된다는 것을 뜻하기 때문에 좀더 큰 SOAP메시지의 경우 적절하지 않다고 볼수 있다. 이 경우 AxiomSoapMessageFactory가 더 적절하다. </div>

AxiomSoapMessageFactory

StAX(Streaming API for XML)에 기초한 AXis 2 Object Model를 사용한다.

<bean id="messageFactory" class="org.springframework.ws.soap.axiom.AxiomSoapMessageFactory">
    <property name="payloadCaching" value="true"/>
</bean>

SOAP 버전 현재 1.1, 1.2 버전을 지원한다. 디폴트는 1.1이다.

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util-2.0.xsd">

    <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
        <property name="soapVersion">
            <util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_12"/>
        </property>
    </bean>

</beans>

MessageContext#

요청(클라이언트측)과 응답(서버측)이라는 두가지를 포함하는 객체이다.

클라이언트 측

클라이언트에서는 webServiceTemplate를 통해 MessageContext가 생성한다.

import java.io.StringReader;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.transport.WebServiceMessageSender;

public class WebServiceClient {

    private static final String MESSAGE = "<message xmlns=\"http://tempuri.org\">Hello Web Service World</message>";

    private final WebServiceTemplate webServiceTemplate = new WebServiceTemplate();

    public void setDefaultUri(String defaultUri) {
        webServiceTemplate.setDefaultUri(defaultUri);
    }

    // send to the configured default URI
    public void simpleSendAndReceive() {
        StreamSource source = new StreamSource(new StringReader(MESSAGE));
        StreamResult result = new StreamResult(System.out);
        webServiceTemplate.sendSourceAndReceiveToResult(source, result);
    }

    // send to an explicit URI
    public void customSendAndReceive() {
        StreamSource source = new StreamSource(new StringReader(MESSAGE));
        StreamResult result = new StreamResult(System.out);
        webServiceTemplate.sendSourceAndReceiveToResult("http://localhost:8080/AnotherWebService", source, result);
    }

}

<beans xmlns="http://www.springframework.org/schema/beans">

    <bean id="webServiceClient" class="WebServiceClient">
        <property name="defaultUri" value="http://localhost:8080/WebService"/>
    </bean>
</beans>

MessageDispatcher#

Spring-WS의 서버측은 XML메시지를 endpoint로 전달하는 클래스로 디자인되었다. 다음은 Spring WS에서의 request를 처리 절차이다.

http://static.springframework.org/spring-ws/site/reference/html/images/sequence.png

MessageDispatcherServlet#

기본적으로 web.xml 파일에 정의할때 사용된다.

WSDL 노출#

<bean id="orders" class="org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition">
    <constructor-arg value="/WEB-INF/wsdl/Orders.wsdl"/>
</bean>

http://localhost:8080/spring-ws/orders.wsdl

XSD에서 WSDL을 동적으로 생성하기#

<bean id="holiday" class="org.springframework.ws.wsdl.wsdl11.DynamicWsdl11Definition">
  <property name="builder">
    <bean class="org.springframework.ws.wsdl.wsdl11.builder.XsdBasedSoap11Wsdl4jDefinitionBuilder">
      <property name="schema" value="/WEB-INF/xsd/Orders.xsd"/>
      <property name="portTypeName" value="Orders"/>
      <property name="locationUri" value="http://localhost:8080/ordersService/"/>
    </bean>
  </property>
</bean>

DynamicWsdl11Definition 는 WSDL을 생성하기 위해 Wsdl11DefinitionBuilder 를 사용한다. 위 예제에서는 XsdBasedSoap11Wsdl4jDefinitionBuilder를 사용했다. 동적으로 WSDL을 생성하기 위해서는 xsd에 request나 response로 끝나는 element가 있어야 한다. 이를테면 다음의 예를 보자.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema elementFormDefault="qualified"
           targetNamespace="http://openframework.or.kr/hr/schemas" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:hr="http://openframework.or.kr/hr/schemas">
    <xs:element name="HolidayRequest">
        <xs:complexType>
            <xs:all>
                <xs:element name="Holiday" type="hr:HolidayType"/>
                <xs:element name="Employee" type="hr:EmployeeType"/>
            </xs:all>
        </xs:complexType>
    </xs:element>

    ....

</xs:schema>

위 소스의 경우 HolidayRequest라는 element가 있다. 이런 경우 자동으로 생성되는 WSDL에는 HolidayRequest 요소와 함께 Holiday라는 operation이 생성된다.

<?xml version="1.0" encoding="UTF-8"?><wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:schema="http://openframework.or.kr/hr/schemas" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://openframework.or.kr/hr/definitions" targetNamespace="http://openframework.or.kr/hr/definitions">
  <wsdl:types>
....
  </wsdl:types>
  <wsdl:message name="HolidayRequest">
....
  </wsdl:message>
  <wsdl:portType name="HumanResource">
    <wsdl:operation name="Holiday">
      <wsdl:input message="tns:HolidayRequest" name="HolidayRequest">
    </wsdl:input>
    </wsdl:operation>
  </wsdl:portType>
....
  </wsdl:binding>
</wsdl:definitions>

DispatcherServlet에 Spring-WS 묶기#

Endpoints#

public interface PayloadEndpoint {

    /**
     * Invokes an operation.
     */
    Source invoke(Source requestthrows Exception;
}

Endpoint는 Spring-WS의 서버측 지원에 대한 핵심이다.

AbstractDomPayloadEndpoint #

package samples;
            
public class SampleEndpoint extends AbstractDomPayloadEndpoint {

    private String responseText;

    public SampleEndpoint(String responseText) {
        this.responseText = responseText;
    }

    protected Element invokeInternal(
            Element requestElement,
            Document documentthrows Exception {
        String requestText = requestElement.getTextContent();
        System.out.println("Request text: " + requestText);

        Element responseElement = document.createElementNS("http://samples""response");
        responseElement.setTextContent(responseText);
        return responseElement;
    }
}

<bean id="sampleEndpoint" class="samples.SampleEndpoint">
    <constructor-arg value="Hello World!"/>
</bean>

위 소스를 사용했을때 응답 메시지는 다음과 같다.

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Body>
        <request xmlns="http://samples">
            Hello
        </request>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Add new attachment

Only authorized users are allowed to upload new attachments.
« This particular version was published on 28-Oct-2007 19:26 by DongGukLee.