본문 바로가기
슬기로운 자바 개발자 생활/스프링 및 자바웹 서비스

spring boot soap wsdl 서비스 만들기

by 슬기로운 동네 형 2024. 6. 9.
반응형

목표

1. SPRING-WS 기반 WSDL 파일을 제공해서 SOAP 통신을 하고자 한다.

2. 서버(WAS) 구성을 해보고 이후, war로 묶어서 톰캣에 올려 놓는다.

3. 이후 클라이언트를 만들어서 통신을 해본다.


 

Apache Axis, Apache CXF 등의 프레임워크들도 존재하며 Spring ws보다 더 간단할 수도 있다.

 

구현

spring-ws로 서버가 되어 서비스를 만들려면 xsd 파일을 만들어서 자바 파일로 변환하는 과정을 거쳐야 한다.cxf나 axis 프레임워크의 경우 자바객체에 어노테이션만 붙여주고 몇가지 설정만 한다면, 손쉽게 wsdl를 만들어준다.

 

1. Rest-api가 나오기 전 xml 기반의 SOAP 

Simple Object Access Protocol

OAP는 HTTP, HTTPS, SMTP 등을 통해서 XML 기반 의 메시지를 컴퓨터 네트워크 상에서 교환하는 프로토콜이다. 뜻과 같이 간단하게 객체로 접근가능한 프로토콜이라는 의미이다.

 

알아보기

 

 

countries.xsd 파일 작성

 

pom.xml

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			
			<!-- tag::xsd[] -->
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>jaxb2-maven-plugin</artifactId>
				<version>3.1.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>
			<!-- end::xsd[] -->
			
		</plugins>
	</build>

 

 

xsd 파일과 메이븐 설정을 했다면, 이클립스에서 아래와 같이 소스를 생성할 수 있다.

프로젝트파일 우클릭 => Run As => Maven generate-sources

* 메이븐이나 그래들로 이렇게 지원을 하는데 자바자체에서 제공을 한다. java/bin 에 들어가서 cmd로 할수도 있는데 단지 그 방법을 IDE로 옮겨 놓은 것이다.

 

실행 과정에서 몇몇 에러가 발생한다.

 

==> 예제가 자바11 버전의 스프링부트 2.5.3 인데 몇몇 의존성 문제가 있다. 이것 저것 문제를 찾았다. pom.xml 재 확인.

현재 스프링 공식 사이트에서는 자바 17 버전으로 예제가 존재한다. 아 이런..11로는 이런저런 의존성이 맞지 않아서 17로 해보니 잘된다. ㅠ.ㅠ 

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.2.0</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>producing-web-service-complete</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>producing-web-service-complete</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>17</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web-services</artifactId>
		</dependency>
		<!-- tag::springws[] -->
		<dependency>
			<groupId>wsdl4j</groupId>
			<artifactId>wsdl4j</artifactId>
		</dependency>
		<!-- end::springws[] -->

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			<!-- tag::xsd[] -->
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>jaxb2-maven-plugin</artifactId>
				<version>3.1.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>
			<!-- end::xsd[] -->
		</plugins>
	</build>

</project>

 

 

에러사항

countries.xsd를 만들거나 복사해서 넣으면 java 파일들이 패키지 형태가 아닌 폴더 형태로 붙는다.

이렇게 되면 main 쪽 자바 폴더에서 임폴트를 못하게 된다. 아래 J자로 생겼다면...문제다.

이 문제를 해결하는 방법은 우선 생성된 io 폴더를 지운다.

 

에러사항도 자바 17버전 그리고 스프링부트 버전 3.2.0로 하면 발생하지 않는다.

 

 

지운 후에 countries.xsd 를 열어서 글자를 하나 지우고 다시 원복해서 저장해본다.

io 파일 삭제

 

저 줄을 지우고 다시 원복 후 저장

이클립스 버그 같다.

혹시나 폴더로 생긴다면. 다시 지우고 io폴더를 패키지 형태로 만들었다가. xsd 파일의 특정부분을 다시 지우고 원복하면 아래처럼 main 하위 소스에서 import 할수 있게 된다.

 

결국은 스프링 부트 3.2.0, 자바 17. 현재 공식 사이트의 예제로 하니 에러 없이 잘된다.

 

WebServiceConfig.java <=== spring ws 를 위한 설정 정보

CountryRepository.java  <=== 테스트를 위한 나라별 정보 하드코딩 정보

CountryEndpoint.java  <=== 실제 클라이언트가 호출시 진입 소스

 

package com.example.demo;

import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ws.config.annotation.EnableWs;
import org.springframework.ws.transport.http.MessageDispatcherServlet;
import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition;
import org.springframework.xml.xsd.SimpleXsdSchema;
import org.springframework.xml.xsd.XsdSchema;

@EnableWs
@Configuration
public class WebServiceConfig {
	@Bean
	public ServletRegistrationBean<MessageDispatcherServlet> messageDispatcherServlet(ApplicationContext applicationContext) {
		MessageDispatcherServlet servlet = new MessageDispatcherServlet();
		servlet.setApplicationContext(applicationContext);
		servlet.setTransformWsdlLocations(true);
		return new ServletRegistrationBean<>(servlet, "/ws/*");
	}

	@Bean(name = "countries")
	public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) {
		DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
		wsdl11Definition.setPortTypeName("CountriesPort");
		wsdl11Definition.setLocationUri("/ws");
		wsdl11Definition.setTargetNamespace("http://spring.io/guides/gs-producing-web-service");
		wsdl11Definition.setSchema(countriesSchema);
		return wsdl11Definition;
	}

	@Bean
	public XsdSchema countriesSchema() {
		return new SimpleXsdSchema(new ClassPathResource("countries.xsd"));
	}
}

 

package com.example.demo;

import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import io.spring.guides.gs_producing_web_service.Country;
import io.spring.guides.gs_producing_web_service.Currency;
import jakarta.annotation.PostConstruct;

@Component
public class CountryRepository {
	private static final Map<String, Country> countries = new HashMap<>();

	@PostConstruct
	public void initData() {
		Country spain = new Country();
		spain.setName("Spain");
		spain.setCapital("Madrid");
		spain.setCurrency(Currency.EUR);
		spain.setPopulation(46704314);

		countries.put(spain.getName(), spain);

		Country poland = new Country();
		poland.setName("Poland");
		poland.setCapital("Warsaw");
		poland.setCurrency(Currency.PLN);
		poland.setPopulation(38186860);

		countries.put(poland.getName(), poland);

		Country uk = new Country();
		uk.setName("United Kingdom");
		uk.setCapital("London");
		uk.setCurrency(Currency.GBP);
		uk.setPopulation(63705000);

		countries.put(uk.getName(), uk);
	}

	public Country findCountry(String name) {
		Assert.notNull(name, "The country's name must not be null");
		return countries.get(name);
	}
}

 

package com.example.demo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;

import io.spring.guides.gs_producing_web_service.GetCountryRequest;
import io.spring.guides.gs_producing_web_service.GetCountryResponse;

@Endpoint
public class CountryEndpoint {
	
	private static Logger logger = LoggerFactory.getLogger(CountryEndpoint.class);
	
	private static final String NAMESPACE_URI = "http://spring.io/guides/gs-producing-web-service";

	private CountryRepository countryRepository;

	@Autowired
	public CountryEndpoint(CountryRepository countryRepository) {
		this.countryRepository = countryRepository;
	}

	@PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest")
	@ResponsePayload
	public GetCountryResponse getCountry(@RequestPayload GetCountryRequest request) {
		
		logger.info("----------------------------------------------------------");
		logger.info("호출 함 자바 17");
		logger.info("----------------------------------------------------------");
		
		GetCountryResponse response = new GetCountryResponse();
		response.setCountry(countryRepository.findCountry(request.getName()));

		return response;
	}
}

 

 

포스트맨 또는 기타 구글 크롬 API 호출 도구를 사용해서 Call 해본다.

 

이클립스 호출 상태

 

 

스프링부트 예제 사이트

https://spring.io/guides/gs/producing-web-service

 

Getting Started | Producing a SOAP web service

In order to provide data to the web service, create a country repository. In this guide, you create a dummy country repository implementation with hardcoded data. The following listing (from src/main/java/com/example/producingwebservice/CountryRepository.j

spring.io

 

반응형

댓글