Criação de Web Service em Java utilizando Metro (JAX-WS) #

A seguir são listadas as alterações necessárias para criar e disponibilizar um Web Service em uma aplicação Java.Além de criar os serviços Web Service, no exemplo a seguir este serviço é denominado myWebService, pode ser necessário alterar algumas configurações conforme descrito em seguida.

Interface do serviço - myWebService.java #

O primeiro passo é criar a interface dos serviços a serem disponibilizados pelo Web Service.A interface deve extender a classe Serializable.O seguinte exemplo mostra um serviço Web Service que aceita um inteiro como parâmetro de entrada e retorna um inteiro como saída.public interface myWebService extends Serializable {    public Integer doSomething(Integer id) throws Exception;}

Implementação do serviço - myWebServiceImpl.java #

É necessário implementar a interface do(s) serviço(s) Web Service, definido anteriormente e definir o que será realizado por ele(s).O que faz o Web Service funcionar são as anotações utilizadas na classe implementada. Estas anotações são utilizadas para gerar o WSDL. As anotações necessárias são:

  • @WebService: define a classe como um Web Service.
  • @WebMethod: define um método como um serviço exposto pelo Web Service.
  • @WebResult: define o retorno de um serviço expost pelo Web Service.
  • @WebParam: define um parâmetro de entrada de um serviço exposto. É interessante que cada parâmetro tenha esta anotação.

Na função doSomething é implementada a lógica deste serviço Web Service, o trabalho que ele deve realizar.

@WebService(serviceName="myService")
public class myWebServiceImpl implements myWebService {
       @WebMethod
       public @WebResult(name="myWS", 
                         targetNamespace="http://impl.myWebService.webServices.sgmp.tjpr.gov/")
                         Integer doSomething(
                    @WebParam(name="id", targetNamespace="http://impl.myWebService.webServices.sgmp.tjpr.gov/")
                    Integer id
       ) throws Exception{
             try {
                    return id * 10 - 2;
            }
             catch ( Exception e ) {
                    throw new Exception( e.getMessage().toString() );
            }
      }
 }

Os arquivos de configuração abaixo devem ser alterados/criados para servidores que não tenham o stack do Metro como o Jetty e o Tomcat. No Glassfish estas alterações não são necessárias pois elas serão realizadas de forma automática no momento da disponibilização dos serviços neste tipo de servidor. Exceto a geração automática do client pelo plugin específico no Maven2 que deverá ser configurada conforme descrito à seguir.

web.xml #

É necessário confirmar que a versão do web-app é maior ou igual a 2.5.As primeiras linhas deste aquivo devem estar conforme exemplificado abaixo:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee|http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">

É necessário adicionar um novo filtro para abrir a sessão do hibernate na requisição do serviço. url-pattern define a parte inicial da url da aplicação onde os Web Services estarão disponibilizados.

<filter-mapping>
<filter-name>OpenSessionInView</filter-name>
<url-pattern>/webservices/*</url-pattern>
</filter-mapping>

É necessário adicionar o listener para os serviços Metro:

<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>

É necessário adicionar o servlet para os serviços Metro.url-pattern define a parte inicial da url da aplicação onde os Web Services estarão disponibilizados.

<servlet>
<description>JAX-WS endpoint - fromjava</description>
<servlet-name>JAX-WS</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-WS</servlet-name>
<url-pattern>/webservices/*</url-pattern>
</servlet-mapping>

sun-jaxws.xml #

Este arquivo deverá ser criado na pasta WEB-INF para os servidores citados acima.O arquivo deve conter os endpoint dos serviços Web Service:<?xml version="1.0" encoding="UTF-8"?><endpoints version="2.0" xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"> <endpoint implementation="gov.tjpr.sgmp.webServices.myWebService.impl.myWebServiceImpl" name="myService" url-pattern="/webservices/myWebService"/></endpoints> Name é o nome definido na anotação @WebService.Url-pattern segue o mesmo padrão definido no servlet-mapping do arquivo web.xml com o nome do serviço único ao final

pom.xml #

É necessário configurar o plugin para que o cliente seja gerado pelo Maven. O wsgen cria automaticamente os artefatos para o Web Service a partir de uma classe (especificada pelo sei).    

<plugin>
             <groupId>org.codehaus.mojo</groupId>
             <artifactId>jaxws-maven-plugin</artifactId>
             <executions>
                    <execution>
                           <id>ws-generateMyWebService-wsdl</id>
                           <goals>
                                  <goal>wsgen</goal>
                           </goals>
                           <configuration>
                                  <sei>gov.tjpr.sgmp.webServices.myWebService.impl.myWebServiceImpl</sei>
                                  <genWsdl>true</genWsdl>
                                  <destDir>${project.build.directory}/jaxws/wsgen/classes</destDir>
                           </configuration>
                    </execution>
             </executions>
       </plugin>

Adicionar as dependências apenas ao profile localhost (somente ao utilizar o Tomcat e Jetty):           

  <dependencies>
                <dependency>
                       <groupId>com.sun.xml.ws</groupId>
                       <artifactId>jaxws-rt</artifactId>
                       <version>2.1.7</version>
                  </dependency> 
<!-- .... -->
  </dependencies>

Testando o Web Service #

Depois de fazer o deploy, o Web Service pode ser testado:

  • Verificando a sua URL, no caso do exemplo seria: http://localhost/projeto/webservices/myWebService
  • Usando a ferramenta SoapUI também disponível em tjpr19\Instaladores\Ferramentas & Aplicativos\Java\WebServices é possível testar seu funcionamento especificando os parâmetros de entrada e verificando os valores de retorno.

Consumindo um Web Service em Java #

pom.xmlÉ interessante adicionar uma propriedade, que definirá qual é a URL do Web Service:

<properties>
...
<domus.webservice>
[[http://portal-dev/domus/webservices/enderecoService|http://portal-dev/domus/webservices/enderecoService]]
</domus.webservice>
...
</properties>

Também, é necessário adicionar a dependência do cliente do Web Service:

<dependency>
<groupId>tjpr</groupId>
<artifactId>domus</artifactId>
<version>1.5.26</version>
<classifier>client</classifier>
</dependency>

application-context.xml

É necessário definir um bean para o Web Service e configurar suas propriedades.Os valores das propriedades do Web Service podem ser obtidos acessando o URL definida no pom.xml, neste caso em: http://portal-dev/domus/webservices/enderecoService

<bean id="webServiceDomus"
class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
<property name="serviceInterface"
value="gov.tjpr.domus.webservices.endereco.EnderecoWebServiceImpl"/>
<property name="wsdlDocumentUrl">
<value>${domus.webservice}?wsdl</value> </property>
<property name="namespaceUri"
value="[[http://impl.endereco.webServices.domus.tjpr.gov/%22/%3E|http://impl.endereco.webServices.domus.tjpr.gov/"/>]]
<property name="serviceName" value="enderecoService"/>
<property name="portName" value="EnderecoWebServiceImplPort"/>
</bean> 

Para utilizar o bean do Web Service é necessário injetá-lo ao service:

<bean id="acordaoService" parent="txProxyTemplate">
<property name="target">
<bean
class="gov.tjpr.sgmp.service.impl.AcordaoServiceImpl">
<property name="acordaoDAO" ref="acordaoDAO" />
<property name="webServiceDomus" ref="webServiceDomus"/>
</bean>
</property>
</bean>

ServiceImpl.java Na classe que utiliza o Web Service é necessário apenas criar um setter e adicionar a sua declaração.As funções disponíveis no Web Service podem ser chamadas normalmente. Para descobrir quais as funções disponíveis basta verificar o WSDL do Web Service.

 private EnderecoWebServiceImpl webServiceDomus;

   public void setWebServiceDomus (EnderecoWebServiceImpl webServiceDomus) {
     this.webServiceDomus = webServiceDomus;
   }

   public MunicipioWS pesquisarMunicipios(String nome){
     return this.webServiceDomus.pesquisarMunicipio(nome);
   } 
 }

Consumindo um Web Service em uma aplicação Delphi #

Instalar WSDL Importer atualizado Primeiramente é necessário instalar uma versão atualizada do WSDL Importer. Esta versão a princípio está disponível em: tjpr19\Instaladores\Ferramentas & Aplicativos\Delphi\wsdlImpUpdate

Importar WSDL para o Delphi É necessário fazer a importação do WSDL para o Delphi.Para fazer a importação, rode o comando WSDLImp.exe <URL do WSDL>.Será gerado um arquivo .pas no mesmo diretório do executável, esse arquivo é o cliente do WebService que deve ser incluído no seu projeto. O arquivo gerado conterá a definição do Web Service e as funções que podem ser chamadas. Por exemplo:

 myWebServiceImpl = interface(IInvokable)
  '{41CC01FF-D28B-4C46-2607-2C5827DE1776}'
  function doSomething(const id: Integer): Integer; stdcall;
 end;

Alterar OPToSOAPDomConv.pas O arquivo OPToSOAPDomConv.pas, localizado na pasta “src”, do novo WSDL Importer deve ser alterado.Na função “InvContextToMsg” de acordo com o trecho abaixo, adicione o valor “true” no parâmetro da função. 

 { If we're sending unwrapped literal params, then skip the method node }
  if not (soLiteralParams in Options) then
  begin
    SoapMethNS := GetSoapNS(IntfMD);
    { Add Method node with appropriate namespace }
    ExtMethName := InvRegistry.GetMethExternalName(IntfMD.Info, MethMD.Name);
    if not (soDocument in Options) then
    begin
      MethNode := BodyNode.AddChild(ExtMethName, SoapMethNS, (SoapMethNS <> ));
      { Use encoding style defined by SOAP 1.1 section 5 }
      { NOTE: We used to put this on the method node; it seems more intuitive on
              the body node; Keep this in mind when investigating interop issues }
      BodyNode.SetAttributeNS(SSoapEncodingAttr, SSoapNameSpace, SSoap11EncodingS5);
    end
    else
    begin
      { In document mode, SoapMethNS is the default namespace }
      MethNode := BodyNode.AddChild(ExtMethName, SoapMethNS, True);
 {$IFDEF FIX_ELEM_NODE_NS}
      ElemNodeNamespace := SoapMethNS;
 {$ENDIF}
    end;
  end 

Alterar o Projeto É necessário incluir duas pastas no “Search Path” do projeto.Para isso abra a janela de opções do projeto: Project / Options, e selecione a aba “Directories/Conditionals”.Note que há uma pasta “src” no novo WSDL Importer, ela deve ser incluída no “Search Path” dentro das opções do seu projeto. Adicione também o diretório “$(DELPHI)\Source\Soap”, logo abaixo da entrada anterior.Ainda nas opções do projeto, adicione as entradas CLEANUP_SOAP_HEADERS e FIX_ELEM_NODE_NS no campo “Conditionals defines”.

Utilizar o Web Service É preciso ter um objeto do tipo THTTPRIO (no exemplo abaixo tem o nome conexaoHttp), este objeto será usado para instanciar o Web Service. Para utilizar o Web Service só é necessário criar um objeto e chamar a função desejada. Exemplo de uso do Web Service:

 function TdtmTeste.Teste: Integer;
  var
  pWebService: myWebServiceImpl;
  begin
   try
    pWebService := GetmyWebServiceImpl(true, , conexaoHttp);
    Result := pWebService.doSomething(10);
    except
   end;
  end;