스프링 soap(wsdl) 다루기

soap 와 wsdl 을 만나다

  • 최근 soap를 사용해야 하는 상황이 발생했다. 관련하여 학습 및 시스템에 적용하였는데 해당 내용을 정리하고자 한다.
  • soap와 wsdl, 마셜링 등 무엇인지 알 수 있었다.
  • 참고한 자료는 스프링 공식 문서이다. 이 글은 이에 대한 간단한 정리이므로 구체적인 내용은 아래 링크를 참고하자.
    • https://spring.io/guides/gs/producing-web-service/
    • https://spring.io/guides/gs/consuming-web-service/

soap 와 wsdl은 무엇인가?

  • soap는 wsdl을 기반으로 통신하는 프로토콜을 의미한다.
  • wsdl이란 무엇인가? xml이다. 우리가 평소에 사용하는 html이 일종의 xml이다.

자바-스프링은 soap 통신의 편의를 위하여 마셜링 기능과 서버의 명세서를 클라이언트에 복사하는 기능을 제공한다.

  • 위의 스프링 공식 문서를 통해 몇 가지 정말로 탁월한 기능들을 접할 수 있었다.
  • 가장 먼저 놀라운 점은 producing-web-service 을 다루는 과정에서 그러했는데, 명세서를 작성하면 이에 따라 클래스 파일을 만들어줬다.

  • resources/countries.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://spring.io/guides/gs-producing-web-service"
           targetNamespace="http://spring.io/guides/gs-producing-web-service" elementFormDefault="qualified">

    <xs:element name="getCountryRequest">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="name" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:element name="getCountryResponse">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="country" type="tns:country"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="country">
        <xs:sequence>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="population" type="xs:int"/>
            <xs:element name="capital" type="xs:string"/>
            <xs:element name="currency" type="tns:currency"/>
        </xs:sequence>
    </xs:complexType>

    <xs:simpleType name="currency">
        <xs:restriction base="xs:string">
            <xs:enumeration value="GBP"/>
            <xs:enumeration value="EUR"/>
            <xs:enumeration value="PLN"/>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>
  • pom.xml
<dependency>
    <groupId>wsdl4j</groupId>
    <artifactId>wsdl4j</artifactId>
</dependency>
<plugin>
	<groupId>org.codehaus.mojo</groupId>
	<artifactId>jaxb2-maven-plugin</artifactId>
	<version>2.5.0</version>
	<executions>
		<execution>
			<id>xjc</id>
			<goals>
				<goal>xjc</goal>
			</goals>
		</execution>
	</executions>
	<configuration>
		<sources>
			<source>${project.basedir}/src/main/resources/countries.xsd</source>
		</sources>
	</configuration>
</plugin>
  • wsdl4j와 jaxb2를 활용하여 countries.xsd에 작성된 내용 그대로의 클래스파일이 생성된다.
  • 예전에 나는 파싱, 바인딩, 마셜링 등 데이터의 변환 과정에서 사용하는 단어들에 대하여 그 차이를 이해하지 못했다. 이번에 직관적으로 이해할 수 있었다. 특정 명세서가 자바 클래스 파일로 변경되는 것이 바로 마셜링이었다.

  • 더 놀라운 점은, 클라이언트가 이러한 명세서를 가져오고 바로 클래스파일로 만든다는 것이었다. 아래의 코드를 보자.

  • pom.xml
<profiles>
	<profile>
		<id>java11</id>
		<activation>
			<jdk>[11,)</jdk>
		</activation>

		<dependencies>
			<dependency>
				<groupId>org.glassfish.jaxb</groupId>
				<artifactId>jaxb-runtime</artifactId>
			</dependency>
		</dependencies>
	</profile>
</profiles>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <!-- tag::wsdl[] -->
        <plugin>
                <groupId>org.jvnet.jaxb2.maven2</groupId>
                <artifactId>maven-jaxb2-plugin</artifactId>
                <version>0.14.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <schemaLanguage>WSDL</schemaLanguage>
                    <generatePackage>com.example.consumingwebservice.wsdl</generatePackage>
                    <schemas>
                        <schema>
                            <url>http://localhost:8080/ws/countries.wsdl</url>
                        </schema>
                    </schemas>
                </configuration>
        </plugin>
        <!-- end::wsdl[] -->
    </plugins>
</build>
  • 위의 pom.xml 중 http://localhost:8080/ws/countries.wsdl 이 보인다. 해당 서버의 해당 메서드에 접근하여, 서버의 것 그대로의 명세서와 클래스 파일을 클라이언트에 복사한다. 와, 난 여기서 놀랐다. 이런 편리한 기능이…! rest api에서는 이런 기능 없나?

  • 어떻게 soap 를 잠깐 건들면서 여러 개념에 대하여 공부하는 계기가 되었다. 내부 구조나 동작 원리는 잘 모르겠지만 자바에 대해 좀 더 알게 된 기분이다. 재밌었다.

혹시 위의 스프링 예제가 동작하지 않을 때.

  • STS 워크스페이스 하나로 두 개의 어플리케이션을 로드하였다. 이 때 클라이언트 어플리케이션이 제대로 빌드 되지 않았다. 이에 대한 해결책으로 서버를 로드하는 주체를 분리하였는데, 하나는 커맨드로 로딩하고 하나는 sts로 돌려서 해결하였다.