diff --git a/2023-05/spring-32-http-client/pom.xml b/2023-05/spring-32-http-client/pom.xml
new file mode 100644
index 00000000..6f78a379
--- /dev/null
+++ b/2023-05/spring-32-http-client/pom.xml
@@ -0,0 +1,36 @@
+
+
+ 4.0.0
+
+ ru.otus
+ spring-32-http-client
+ 1.0
+
+ pom
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.1.4
+
+
+
+
+ rest-template
+ soap-client
+ soap-server
+
+
+
+ 17
+ 17
+ UTF-8
+ UTF-8
+ 3.1.2
+ 10.9.1
+ https://raw.githubusercontent.com/OtusTeam/Spring/master/checkstyle.xml
+
+
+
diff --git a/2023-05/spring-32-http-client/rest-template/pom.xml b/2023-05/spring-32-http-client/rest-template/pom.xml
new file mode 100644
index 00000000..77cefc6b
--- /dev/null
+++ b/2023-05/spring-32-http-client/rest-template/pom.xml
@@ -0,0 +1,83 @@
+
+
+ 4.0.0
+
+ ru.otus
+ rest-template
+ 1.0-SNAPSHOT
+
+
+ ru.otus
+ spring-32-http-client
+ 1.0
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-cache
+
+
+
+
+ org.springframework.retry
+ spring-retry
+
+
+ org.aspectj
+ aspectjweaver
+
+
+
+ org.springframework
+ spring-webflux
+
+
+ io.projectreactor.netty
+ reactor-netty
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ 2021.0.3
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/Main.java b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/Main.java
new file mode 100644
index 00000000..e8152d45
--- /dev/null
+++ b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/Main.java
@@ -0,0 +1,26 @@
+package ru.otus.spring;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.ApplicationContext;
+import org.springframework.retry.annotation.EnableRetry;
+
+import lombok.extern.slf4j.Slf4j;
+import ru.otus.spring.service.MainService;
+
+@Slf4j
+@EnableCaching
+@EnableRetry
+@EnableFeignClients
+@SpringBootApplication
+public class Main {
+
+ public static void main(String[] args) {
+ ApplicationContext ctx = SpringApplication.run(Main.class, args);
+ MainService service = ctx.getBean(MainService.class);
+ service.start();
+
+ }
+}
diff --git a/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/config/CacheConfig.java b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/config/CacheConfig.java
new file mode 100644
index 00000000..00578e94
--- /dev/null
+++ b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/config/CacheConfig.java
@@ -0,0 +1,15 @@
+package ru.otus.spring.config;
+
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class CacheConfig {
+
+ @Bean
+ public CacheManager cacheManager() {
+ return new ConcurrentMapCacheManager("countries");
+ }
+}
diff --git a/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/config/ClientConfiguration.java b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/config/ClientConfiguration.java
new file mode 100644
index 00000000..70410f9c
--- /dev/null
+++ b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/config/ClientConfiguration.java
@@ -0,0 +1,15 @@
+package ru.otus.spring.config;
+
+import org.springframework.context.annotation.Bean;
+
+import feign.RequestInterceptor;
+
+public class ClientConfiguration {
+
+ @Bean
+ public RequestInterceptor requestInterceptor() {
+ return requestTemplate -> {
+ requestTemplate.query("access_key", "[!!!Your key!!!]");
+ };
+ }
+}
diff --git a/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/dto/Country.java b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/dto/Country.java
new file mode 100644
index 00000000..63b8da46
--- /dev/null
+++ b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/dto/Country.java
@@ -0,0 +1,20 @@
+package ru.otus.spring.dto;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@ToString
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class Country {
+
+ private String name;
+
+ private String alpha3Code;
+
+}
diff --git a/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/CountryService.java b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/CountryService.java
new file mode 100644
index 00000000..3a1977f5
--- /dev/null
+++ b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/CountryService.java
@@ -0,0 +1,8 @@
+package ru.otus.spring.service;
+
+import ru.otus.spring.dto.Country;
+
+public interface CountryService {
+
+ Country findByCode(String id);
+}
diff --git a/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/FeignCountryService.java b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/FeignCountryService.java
new file mode 100644
index 00000000..a83cd830
--- /dev/null
+++ b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/FeignCountryService.java
@@ -0,0 +1,21 @@
+package ru.otus.spring.service;
+
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.retry.annotation.Backoff;
+import org.springframework.retry.annotation.Retryable;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import ru.otus.spring.config.ClientConfiguration;
+import ru.otus.spring.dto.Country;
+
+@FeignClient(value = "countrylayer", url = "http://api.countrylayer.com/v2/", configuration = ClientConfiguration.class)
+@Cacheable("countries")
+@Retryable(retryFor = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000))
+public interface FeignCountryService {
+ @RequestMapping(method = RequestMethod.GET, value = "/alpha/{code}", produces = "application/json")
+ Country findByCode(@PathVariable("code") String code);
+
+}
diff --git a/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/MainService.java b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/MainService.java
new file mode 100644
index 00000000..995a8ec8
--- /dev/null
+++ b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/MainService.java
@@ -0,0 +1,6 @@
+package ru.otus.spring.service;
+
+public interface MainService {
+
+ void start();
+}
diff --git a/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/MainServiceImpl.java b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/MainServiceImpl.java
new file mode 100644
index 00000000..5ba46236
--- /dev/null
+++ b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/MainServiceImpl.java
@@ -0,0 +1,22 @@
+package ru.otus.spring.service;
+
+import org.springframework.stereotype.Service;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import ru.otus.spring.dto.Country;
+
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class MainServiceImpl implements MainService {
+ private final RestCountryService countryService;
+
+ @Override
+ public void start() {
+ Country country = countryService.findByCode("col");
+ log.info("Find {}", country);
+// country = countryService.findByCode("rus");
+// log.info("Find {}", country);
+ }
+}
diff --git a/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/RestCountryService.java b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/RestCountryService.java
new file mode 100644
index 00000000..9432af7e
--- /dev/null
+++ b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/RestCountryService.java
@@ -0,0 +1,23 @@
+package ru.otus.spring.service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestOperations;
+import org.springframework.web.client.RestTemplate;
+
+import ru.otus.spring.dto.Country;
+
+@Service
+public class RestCountryService implements CountryService {
+
+ private static final Logger log = LoggerFactory.getLogger(RestCountryService.class);
+
+ private final RestOperations rest = new RestTemplate();
+
+ @Override
+ public Country findByCode(String id) {
+ log.info("Rest Request");
+ return rest.getForObject("http://api.countrylayer.com/v2/alpha/" + id + "?access_key=[!!!Your key!!!]", Country.class);
+ }
+}
diff --git a/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/WebCountryService.java b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/WebCountryService.java
new file mode 100644
index 00000000..b20c04a3
--- /dev/null
+++ b/2023-05/spring-32-http-client/rest-template/src/main/java/ru/otus/spring/service/WebCountryService.java
@@ -0,0 +1,45 @@
+package ru.otus.spring.service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import reactor.core.publisher.Mono;
+import ru.otus.spring.dto.Country;
+
+@Service
+public class WebCountryService implements CountryService {
+
+ private static final Logger log = LoggerFactory.getLogger(WebCountryService.class);
+
+ private final WebClient webClient = WebClient.builder()
+ .filter(errorHandler())
+ .build();
+
+ @Override
+ public Country findByCode(String id) {
+ log.info("Web client Request");
+ return webClient.get()
+ .uri("http://api.countrylayer.com/v2/alpha/" + id + "?access_key=[!!!Your key!!!]")
+ .retrieve()
+ .bodyToMono(Country.class)
+ .block();
+ }
+
+ private static ExchangeFilterFunction errorHandler() {
+ return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
+ if (clientResponse.statusCode().is5xxServerError()) {
+ return clientResponse.bodyToMono(String.class)
+ .flatMap(errorBody -> Mono.error(new RuntimeException(errorBody)));
+ } else if (clientResponse.statusCode().is4xxClientError()) {
+ return clientResponse.bodyToMono(String.class)
+ .flatMap(errorBody -> Mono.error(new RuntimeException(errorBody)));
+ } else {
+ return Mono.just(clientResponse);
+ }
+ });
+ }
+
+}
diff --git a/2023-05/spring-32-http-client/rest-template/src/main/resources/application.yml b/2023-05/spring-32-http-client/rest-template/src/main/resources/application.yml
new file mode 100644
index 00000000..c461b008
--- /dev/null
+++ b/2023-05/spring-32-http-client/rest-template/src/main/resources/application.yml
@@ -0,0 +1,8 @@
+server:
+ port: 8081
+
+logging:
+ level:
+ org:
+ springframework:
+ web: debug
diff --git a/2023-05/spring-32-http-client/soap-client/pom.xml b/2023-05/spring-32-http-client/soap-client/pom.xml
new file mode 100644
index 00000000..cfcb0d4e
--- /dev/null
+++ b/2023-05/spring-32-http-client/soap-client/pom.xml
@@ -0,0 +1,68 @@
+
+
+ 4.0.0
+
+ ru.otus
+ soap-client
+ 1.0
+
+
+ ru.otus
+ spring-32-http-client
+ 1.0
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web-services
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ com.sun.xml.ws
+ jaxws-maven-plugin
+ 3.0.0
+
+
+
+ wsimport
+
+
+
+
+ hello.wsdl
+
+ src/main/resources/countries.wsdl
+
+
+ true
+
+
+
+
+
+
diff --git a/2023-05/spring-32-http-client/soap-client/src/main/java/hello/ClientApp.java b/2023-05/spring-32-http-client/soap-client/src/main/java/hello/ClientApp.java
new file mode 100644
index 00000000..0a136b5d
--- /dev/null
+++ b/2023-05/spring-32-http-client/soap-client/src/main/java/hello/ClientApp.java
@@ -0,0 +1,30 @@
+package hello;
+
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+
+import hello.wsdl.GetCountryResponse;
+
+@SpringBootApplication
+public class ClientApp {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ClientApp.class, args);
+ }
+
+ @Bean
+ CommandLineRunner lookup(CountryClient quoteClient) {
+ return args -> {
+ String country = "Spain";
+
+ if (args.length > 0) {
+ country = args[0];
+ }
+ GetCountryResponse response = quoteClient.getCountry(country);
+ System.err.println(response.getCountry().getCurrency());
+ };
+ }
+
+}
diff --git a/2023-05/spring-32-http-client/soap-client/src/main/java/hello/CountryClient.java b/2023-05/spring-32-http-client/soap-client/src/main/java/hello/CountryClient.java
new file mode 100644
index 00000000..63e39a91
--- /dev/null
+++ b/2023-05/spring-32-http-client/soap-client/src/main/java/hello/CountryClient.java
@@ -0,0 +1,28 @@
+package hello;
+
+import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
+import org.springframework.ws.soap.client.core.SoapActionCallback;
+
+import hello.wsdl.GetCountryRequest;
+import hello.wsdl.GetCountryResponse;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class CountryClient extends WebServiceGatewaySupport {
+
+ public GetCountryResponse getCountry(String country) {
+
+ GetCountryRequest request = new GetCountryRequest();
+ request.setName(country);
+
+ log.info("Requesting location for {}", country);
+
+ GetCountryResponse response = (GetCountryResponse) getWebServiceTemplate()
+ .marshalSendAndReceive("http://localhost:8080/ws/countries", request,
+ new SoapActionCallback(
+ "http://otus.ru/hello/web-service/GetCountryRequest"));
+
+ return response;
+ }
+
+}
diff --git a/2023-05/spring-32-http-client/soap-client/src/main/java/hello/CountryConfiguration.java b/2023-05/spring-32-http-client/soap-client/src/main/java/hello/CountryConfiguration.java
new file mode 100644
index 00000000..c795ee3a
--- /dev/null
+++ b/2023-05/spring-32-http-client/soap-client/src/main/java/hello/CountryConfiguration.java
@@ -0,0 +1,28 @@
+package hello;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.oxm.jaxb.Jaxb2Marshaller;
+
+@Configuration
+public class CountryConfiguration {
+
+ @Bean
+ public Jaxb2Marshaller marshaller() {
+ Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
+ // this package must match the package in the specified in
+ // pom.xml
+ marshaller.setContextPath("hello.wsdl");
+ return marshaller;
+ }
+
+ @Bean
+ public CountryClient countryClient(Jaxb2Marshaller marshaller) {
+ CountryClient client = new CountryClient();
+ client.setDefaultUri("http://localhost:8080/ws");
+ client.setMarshaller(marshaller);
+ client.setUnmarshaller(marshaller);
+ return client;
+ }
+
+}
diff --git a/2023-05/spring-32-http-client/soap-client/src/main/resources/application.yml b/2023-05/spring-32-http-client/soap-client/src/main/resources/application.yml
new file mode 100644
index 00000000..1aa84da6
--- /dev/null
+++ b/2023-05/spring-32-http-client/soap-client/src/main/resources/application.yml
@@ -0,0 +1,6 @@
+logging:
+ level:
+ hello: INFO
+ org:
+ springframework:
+ ws: DEBUG
diff --git a/2023-05/spring-32-http-client/soap-client/src/main/resources/countries.wsdl b/2023-05/spring-32-http-client/soap-client/src/main/resources/countries.wsdl
new file mode 100644
index 00000000..061e18f5
--- /dev/null
+++ b/2023-05/spring-32-http-client/soap-client/src/main/resources/countries.wsdl
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2023-05/spring-32-http-client/soap-server/pom.xml b/2023-05/spring-32-http-client/soap-server/pom.xml
new file mode 100644
index 00000000..3c8c8fb8
--- /dev/null
+++ b/2023-05/spring-32-http-client/soap-server/pom.xml
@@ -0,0 +1,68 @@
+
+
+ 4.0.0
+
+ ru.otus
+ soap-server
+ 1.0
+
+
+ ru.otus
+ spring-32-http-client
+ 1.0
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web-services
+
+
+ wsdl4j
+ wsdl4j
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.codehaus.mojo
+ jaxb2-maven-plugin
+ 3.1.0
+
+
+ xjc
+
+ xjc
+
+
+
+
+
+ ${project.basedir}/src/main/resources/countries.xsd
+
+
+ ru.otus.hello.web_service
+
+
+
+
+
+
diff --git a/2023-05/spring-32-http-client/soap-server/src/main/java/hello/CountryEndpoint.java b/2023-05/spring-32-http-client/soap-server/src/main/java/hello/CountryEndpoint.java
new file mode 100644
index 00000000..24d8dc92
--- /dev/null
+++ b/2023-05/spring-32-http-client/soap-server/src/main/java/hello/CountryEndpoint.java
@@ -0,0 +1,31 @@
+package hello;
+
+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 ru.otus.hello.web_service.GetCountryRequest;
+import ru.otus.hello.web_service.GetCountryResponse;
+
+@Endpoint
+public class CountryEndpoint {
+ private static final String NAMESPACE_URI = "http://otus.ru/hello/web-service";
+
+ private final CountryRepository countryRepository;
+
+ @Autowired
+ public CountryEndpoint(CountryRepository countryRepository) {
+ this.countryRepository = countryRepository;
+ }
+
+ @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest")
+ @ResponsePayload
+ public GetCountryResponse getCountry(@RequestPayload GetCountryRequest request) {
+ GetCountryResponse response = new GetCountryResponse();
+ response.setCountry(countryRepository.findCountry(request.getName()));
+
+ return response;
+ }
+}
diff --git a/2023-05/spring-32-http-client/soap-server/src/main/java/hello/CountryRepository.java b/2023-05/spring-32-http-client/soap-server/src/main/java/hello/CountryRepository.java
new file mode 100644
index 00000000..ebd8b038
--- /dev/null
+++ b/2023-05/spring-32-http-client/soap-server/src/main/java/hello/CountryRepository.java
@@ -0,0 +1,48 @@
+package hello;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+
+import jakarta.annotation.PostConstruct;
+import ru.otus.hello.web_service.Country;
+import ru.otus.hello.web_service.Currency;
+
+@Component
+public class CountryRepository {
+ private static final Map 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);
+ }
+}
diff --git a/2023-05/spring-32-http-client/soap-server/src/main/java/hello/ServerApp.java b/2023-05/spring-32-http-client/soap-server/src/main/java/hello/ServerApp.java
new file mode 100644
index 00000000..d5417373
--- /dev/null
+++ b/2023-05/spring-32-http-client/soap-server/src/main/java/hello/ServerApp.java
@@ -0,0 +1,12 @@
+package hello;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class ServerApp {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ServerApp.class, args);
+ }
+}
diff --git a/2023-05/spring-32-http-client/soap-server/src/main/java/hello/WebServiceConfig.java b/2023-05/spring-32-http-client/soap-server/src/main/java/hello/WebServiceConfig.java
new file mode 100644
index 00000000..09e1bdb2
--- /dev/null
+++ b/2023-05/spring-32-http-client/soap-server/src/main/java/hello/WebServiceConfig.java
@@ -0,0 +1,40 @@
+package hello;
+
+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.config.annotation.WsConfigurerAdapter;
+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 extends WsConfigurerAdapter {
+ @Bean
+ public ServletRegistrationBean 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://otus.ru/hello/web-service");
+ wsdl11Definition.setSchema(countriesSchema);
+ return wsdl11Definition;
+ }
+
+ @Bean
+ public XsdSchema countriesSchema() {
+ return new SimpleXsdSchema(new ClassPathResource("countries.xsd"));
+ }
+}
diff --git a/2023-05/spring-32-http-client/soap-server/src/main/resources/application.yml b/2023-05/spring-32-http-client/soap-server/src/main/resources/application.yml
new file mode 100644
index 00000000..4b4d02dc
--- /dev/null
+++ b/2023-05/spring-32-http-client/soap-server/src/main/resources/application.yml
@@ -0,0 +1,3 @@
+logging:
+ level:
+ root: debug
\ No newline at end of file
diff --git a/2023-05/spring-32-http-client/soap-server/src/main/resources/countries.xsd b/2023-05/spring-32-http-client/soap-server/src/main/resources/countries.xsd
new file mode 100644
index 00000000..806a4136
--- /dev/null
+++ b/2023-05/spring-32-http-client/soap-server/src/main/resources/countries.xsd
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2023-05/spring-32-http-client/soap-server/src/test/java/hello/ApplicationIntegrationTests.java b/2023-05/spring-32-http-client/soap-server/src/test/java/hello/ApplicationIntegrationTests.java
new file mode 100644
index 00000000..4e85b9e3
--- /dev/null
+++ b/2023-05/spring-32-http-client/soap-server/src/test/java/hello/ApplicationIntegrationTests.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2014-2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package hello;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.test.web.server.LocalServerPort;
+import org.springframework.oxm.jaxb.Jaxb2Marshaller;
+import org.springframework.util.ClassUtils;
+import org.springframework.ws.client.core.WebServiceTemplate;
+
+import ru.otus.hello.web_service.GetCountryRequest;
+
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
+public class ApplicationIntegrationTests {
+
+ private final Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
+
+ @LocalServerPort
+ private int port = 0;
+
+ @BeforeEach
+ public void init() throws Exception {
+ marshaller.setPackagesToScan(ClassUtils.getPackageName(GetCountryRequest.class));
+ marshaller.afterPropertiesSet();
+ }
+
+ @Test
+ public void testSendAndReceive() {
+ WebServiceTemplate ws = new WebServiceTemplate(marshaller);
+ GetCountryRequest request = new GetCountryRequest();
+ request.setName("Spain");
+
+ assertThat(ws.marshalSendAndReceive("http://localhost:" + port + "/ws", request)).isNotNull();
+ }
+}
\ No newline at end of file