스프링 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로 돌려서 해결하였다.