SOAP vs REST, diferentes formas de se comunicar.

Kleber Santos
5 min readJul 3, 2022

--

A troca de mensagens entre aplicações permite que sistemas, desenvolvidos em diferentes plataformas, sejam compatíveis e se comuniquem. Tal comunicação pode ser dada de forma universal, por intermédio de formatos como XML, JSON, CSV, dentre outros. Serviços WEB por sua vez, podem fornecer um conjunto de padrões e rotinas que permitam esta comunicação. Tais rotinas denominadas como Interface de Programação de Aplicação (API) são definidas por duas abordagens diferentes de transmissão, possibilitando esta comunicação entre aplicações WEB: SOAP e REST.

SOAP (simple object access protocol) é um protocolo de requisitos específicos, mantido pela World Wide Web Consortium (W3C). Oferece segurança integrada e transações em conformidade, normalmente atendendo à necessidades empresariais, devido à segurança, atomicidade, consistência, isolamento e durabilidade (ACID), que por sua vez, é um conjunto de propriedades para assegurar transações confiáveis de bancos de dados.

Devido ao fato de ser um protocolo, regras integradas são impostas, aumentando a complexidade e overhead no transporte de dados. Tal abordagem utiliza o formato XML para envio e recebimento de mensagens, e pode ser descrito pela definição WSDL, descrevendo o início e fim de um serviço WEB.

REST (representational state transfer) por sua vez, é um conjunto de diretrizes que oferece uma implementação flexível. São leves e ideais para contextos mais modernos, como o desenvolvimento de aplicações mobile e serverless.

Trata-se de um conjunto de princípios arquiteturais e não de um protocolo, sendo assim, tem regras mais claras, leves e fáceis de configurar, diminuindo o overhead na troca de mensagens e permitindo a utilização de diversos padrões para isso, tais como o JSON, XML, CSV, dentre outros.

Aproximadamente 70% das aplicações hoje, utilizam a abordagem Rest para se comunicar.

A seguir, abordaremos duas aplicações simples, providas pela comunicação em SOAP, e que forneça um adapter para uma API Rest. A aplicação servidora, proverá comunicação com uma base de dados H2 em JPA e disponibilizará uma API em SOAP, que através de um arquivo XSD, irá gerar um WSDL, permitindo tal comunicação. Já a aplicação cliente, se comunicará em SOAP com a servidora através do WSDL gerado e proverá uma API em Rest para se comunicar com outros meios.

Os projetos utilizam a dependência wsdl4j em seus arquivos de compilação:

<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</dependency>

Aplicação Servidora:

O domínio do serviço web será definido por um arquivo XSD e será exposto automaticamente como um WSDL, permitindo trabalhar com requisições em XML:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://ksgprod.com/soap-poc"
xmlns:tns="http://ksgprod.com/soap-poc"
elementFormDefault="qualified">

<xs:element name="InsertCustomerRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="CustomerDetail" type="tns:CustomerDetail"/>
</xs:sequence>
</xs:complexType>
</xs:element>

<xs:element name="InsertCustomerResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="status" type="tns:Status"/>
</xs:sequence>
</xs:complexType>
</xs:element>

<xs:element name="GetCustomerDetailRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:int"/>
</xs:sequence>
</xs:complexType>
</xs:element>

<xs:element name="GetCustomerDetailResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="CustomerDetail" type="tns:CustomerDetail"/>
</xs:sequence>
</xs:complexType>
</xs:element>

<xs:element name="GetAllCustomerDetailRequest">
<xs:complexType>
</xs:complexType>
</xs:element>

<xs:element name="GetAllCustomerDetailResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="CustomerDetail" type="tns:CustomerDetail" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>

<xs:element name="DeleteCustomerRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:int"/>
</xs:sequence>
</xs:complexType>
</xs:element>

<xs:element name="DeleteCustomerResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="status" type="tns:Status"/>
</xs:sequence>
</xs:complexType>
</xs:element>

<xs:simpleType name="Status">
<xs:restriction base="xs:string">
<xs:enumeration value="SUCCESS"/>
<xs:enumeration value="FAILURE"/>
</xs:restriction>
</xs:simpleType>

<xs:complexType name="CustomerDetail">
<xs:sequence>
<xs:element name="id" type="xs:int" />
<xs:element name="name" type="xs:string"/>
<xs:element name="phone" type="xs:string"/>
<xs:element name="email" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>

Para isso, é necessário importá-lo na estrutura de pasta resources da aplicação servidora e configurar o pom.xml desta aplicação, informando o caminho do arquivo e a estrutura de pacotes a ser gerado os objetos convertidos (binding):

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.14.0</version>
<executions>
<execution>
<id>Customer</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<schemaLanguage>WSDL</schemaLanguage>
<generatePackage>br.com.ksgprod.soap.wsdl</generatePackage>
<schemaDirectory>${project.basedir}/src/main/resources</schemaDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

As classes serão geradas em tempo de compilação, partindo do arquivo XDS importado, através do plugin: jaxb2-maven-plugin.

Uma vez startada a aplicação servidora, poderemos acessar o WSDL através do caminho: http://localhost:8080/ws/customers.wsdl

A geração do WSDL só será possível após criar e configurar nossa aplicação provedora dos serviços web. Para isso, vamos começar pelo arquivo de configuração: WebServiceConfiguration

@EnableWs: permite habilitar a aplicação Spring para serviços web.

Além disso, precisaremos definir nosso MessageDispatcherServlet como um Bean, que servirá como um servlet para o envio simplificado de mensagens web, ao passo que terá a função de identificar os endpoints específicos do SOAP web service:

@Bean
public ServletRegistrationBean<MessageDispatcherServlet> messageDispatcherServlet(ApplicationContext context) {
MessageDispatcherServlet mds = new MessageDispatcherServlet();
mds.setApplicationContext(context);
mds.setTransformWsdlLocations(true);
return new ServletRegistrationBean<MessageDispatcherServlet>(mds, "/ws/*");

}

Outro Bean, não menos importante que precisaremos implementar, será o nosso XsdSchema, que permitirá enfim, gerar o WSDL. Precisaremos descriminar o caminho de origem para o arquivo XSD importado:

@Bean
public XsdSchema customerSchema() {
return new SimpleXsdSchema(new ClassPathResource("customer-information.xsd"));}

Algumas definições para o WSDL deverão ser passadas através do XsdSchema, tais como:

PortType: Funciona como uma interface para o WSDL, provendo as regras para o contrato dos serviços da sua API.

LocationUri: Defini o endereço de acesso aos serviços.

Os endpoints da nossa aplicação servidora serão expostos na controller. Algumas ressalvas são importantes para melhor compreensão deles:

Namespace: Torna o XML único e exclusivo;
Element names: Define os elementos de request e response do XML;

@Endpoint: Define a classe como um endpoint, suportando os serviços criados pelo XSD;
@PayloadRoot: Permite descriminar o namespace e localpart, mapeando o XML definido através do XSD;
@RequestPayload: Possibilita conversão em objetos Java, do XML recebido;
@ResponsePayload: Possibilita conversão dos objetos Java, no XML de resposta;

Aplicação Cliente:

Sendo assim, podemos construir a aplicação cliente, que por sua vez, importará o WSDL, permitindo se comunicar via SOAP com a aplicação servidora. No pom.xml da aplicação cliente, precisaremos configurar a URL do WSDL gerado, assim como a estrutura de pacotes para as classes convertidas:

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<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>br.com.ksgprod.soap.wsdl</generatePackage>
<schemas>
<schema>
<url>http://localhost:8080/ws/customers.wsdl</url>
</schema>
</schemas>
</configuration>
</plugin>
</plugins>
</build>

Para as requisições SOAP feitas pela nossa aplicação cliente à servidora, implementaremos um cliente de requisições SOAP estendendo da WebServiceGatewaySupport, permitindo acesso aos serviços WEB.

Para a nossa aplicação cliente, também precisaremos de algumas configurações. Primeiramente, teremos que instanciar a classe Jaxb2Marshaller como Bean, setando como contexto, o apontamento para a coleção de objetos de domínio gerados através do WSDL, fornecido pela aplicação servidora:

@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("br.com.ksgprod.soap.wsdl");
return marshaller;
}

O marshaller usará tais objetos de domínio para serializar e desserializar os dados fornecidos pelo XML das requisições SOAP, em POJOs.

Também precisamos instanciar um Bean para o nosso cliente de requisições, informando a URI do serviço fornecido pela aplicação servidora:

@Bean
public CustomerClient customerClientMarshaller(Jaxb2Marshaller marshaller) {
CustomerClient client = new CustomerClient();
client.setDefaultUri(defaultUri);
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
return client;
}

O código completo das aplicações você encontra no GitHub Cliente e Servidor para baixar.

Os serviços Rest da aplicação cliente, poderão ser importados através da collection “POC - SOAP.postman_collection.json” disponível no código da aplicação.

Vimos então neste tutorial uma breve abordagem na utilização de APIs SOAP e Rest para comunicação entre aplicações WEB. Até a próxima!

--

--

Kleber Santos
Kleber Santos

Written by Kleber Santos

Bacharel em Ciência da Computação, Especialista em Sistemas WEB, músico, pai de pets e de plantas. =p

No responses yet