Implementando Serviços Web MO818 – Tópicos em Redes de Computadores Prof. Dr. Edmundo Madeira Instituto de Computação - Unicamp 27/9/2005 Francisco Hoyos 1 Tópicos Introdução Alguns conceitos de .NET Serviços web na plataforma .NET Serviços web na plataforma J2EE Comparação J2EE x .NET Considerações finais Referências 27/9/2005 Francisco Hoyos 2 Introdução J2EE e .NET são duas das principais plataformas para desenvolvimento, execução e consumo de serviços web. No que consiste o suporte ao usuário e desenvolvedor de serviços web nessas plataformas? Qual ambiente de execução elas oferecem aos serviços? 27/9/2005 Francisco Hoyos 3 .NET: Definição “.NET é a estratégia da Microsoft para conectar sistemas, informação e dispositivos através de web services para que as pessoas possam colaborar e comunicar-se mais efetivamente.” “A Microsoft oferece uma completa gama de software que ajuda organizações e indivíduos a se beneficiarem da conectividade baseada em web services: ferramentas de desenvolvimento Visual Studio .NET, Windows Server System que hospeda web services e aplicações para desktop como Office, que consomem web services.” 27/9/2005 Francisco Hoyos 4 .NET: Origens Em outubro de 2000, Microsoft, HP e Intel submeteram as especificações da linguagem C# e da Common Language Infrastructure (CLI) à ECMA (European Computer Manufacturers Association) para padronização. Em dezembro de 2001 ambas foram aprovadas pela ECMA e em 2003 pela ISO. 27/9/2005 Francisco Hoyos 5 .NET: Common Language Infrastructure A CLI inclui: Common Intermediate Language (CIL) linguagem independente de plataforma Common Type System (CTS) conjunto de tipos e operações compartilhados por várias linguagens de programação Common Language Specification (CLS) toda linguagem de programação “.NET- compliant” deve atender a essa especificação 27/9/2005 Francisco Hoyos 6 .NET: Plataforma O .NET Framework é composto pelo Common Language Runtime e a .NET Framework class library. Enterprise Servers incluem SQL Server, Exchange Server, BizTalk, Commerce Server. 27/9/2005 Francisco Hoyos 7 .NET: CLR O CLR é a implementação Microsoft da especificação CLI. Quando uma aplicação .NET é executada, o CLR gerencia o carregamento e a execução do código e provê vários serviços “runtime” à aplicação, como: gerenciamento de memória (garbage collection), de threads e de segurança. 27/9/2005 Francisco Hoyos 8 .NET: execução de código nativo Aplicações .NET são compiladas para MSIL (Microsoft Intermediate Language, o mesmo que CIL). Quando a aplicação é executada pela primeira vez, o runtime faz uma compilação just-in-time para converter o código MSIL para código de máquina. 27/9/2005 Francisco Hoyos 9 .NET: execução no CLR 27/9/2005 Francisco Hoyos 10 .NET: CLS A CLS (Common Language Specification) define um conjunto de tipos de dados que podem ser usados por qualquer linguagem “.NET-compliant”. Isso permite completa integração entre aplicações desenvolvidas em linguagens diferentes: 27/9/2005 um tipo definido em uma linguagem pode ser herdado em outra linguagem exceções podem ser lançadas de uma linguagem e capturadas em uma outra Francisco Hoyos 11 .NET: managed/unmanaged code Código feito para .NET é chamado managed code e pode dispor dos serviços oferecidos pelo runtime .NET. Qualquer outro código é chamado unmanaged code, pode ser executado pelo CLR, mas não tem acesso aos serviços deste. 27/9/2005 Francisco Hoyos 12 .NET: Framework Class Library Pode ser dividida em quatro grupos: 27/9/2005 Base Class Library (BCL): funcionalidades comuns (ex: tipos de dados “core”) ADO.NET e XML: acesso e manipulação de dados (tipicamente obtidos de um banco de dados); conversão dos dados para XML Windows Forms: desenvolvimento de aplicações Windows tradicionais para desktop (“controls”) ASP.NET: desenvolvimento de aplicações web Francisco Hoyos 13 ASP.NET Sucessor da tecnologia Active Server Pages. Simplificação do processo de desenvolvimento de serviços web. Modelo “web forms” para desenvolvimento de interfaces para web browser. “Controls” presentes nas web forms executam no servidor e não no cliente. “Look and feel” muito semelhante ao das Windows forms. 27/9/2005 Francisco Hoyos 14 ASP.NET Páginas com extensão .aspx. Quando um browser requisita uma página aspx, o “runtime” ASP.NET compila o conteúdo numa classe .NET. A partir daí essa classe processa os acessos à página original. A lógica do programa pode ser fisicamente separada do HTML da página através da técnica “code-behind”. 27/9/2005 Francisco Hoyos 15 .NET Web Services Um dos principais focos da plataforma .NET. Classes .NET pré-existentes podem ter seus métodos facilmente expostos como serviços web. Um serviço web é definido através de uma página .asmx. 27/9/2005 Francisco Hoyos 16 Servidor “na raça” Receber requisição SOAP via HTTP Usar XML parser para obter nome da operação invocada e seus parâmetros Montar mensagem SOAP de resposta “manualmente”, usando uma biblioteca XML Enviar resposta SOAP via HTTP 27/9/2005 Francisco Hoyos 17 Serviço web definido no .asmx <@% WebService class="MathServiceJit" language="C#"%> using System.Web.Services; public class MathServiceJit { [WebMethod] public double Add(double x, double y) { return x + y; } [WebMethod] public double Subtract(double x, double y) { return x - y; } } 27/9/2005 Francisco Hoyos 18 Serviço web fora do .asmx: arquivo fonte C# using System.Web.Services; public class MathService { [WebMethod] public double Add(double x, double y) { return x + y; } [WebMethod] public double Subtract(double x, double y) { return x - y; } } 27/9/2005 Francisco Hoyos 19 Serviço web fora do .asmx: página .asmx <@% WebService class="MathService" language="C#"%> OU <@% WebService class="MathService"%> OU <@% WebService class=“MyNS.MathService, MyAssembly"%> A forma recomendada de implementação é manter e compilar separadamente a classe que implementa o serviço web. No Visual Studio .NET a diretiva @WebService é adicionada automaticamente ao arquivo .asmx. 27/9/2005 Francisco Hoyos 20 Atributo WebService [WebService(Namespace="http://www.notashop.com/wscr", Description="SimpleService1", Name="Try This Out")] public class MyService { ... } Namespace deve ser usado quando o serviço for disponibilizado. Se não for especificado, http://tempuri.org será automaticamente usado. 27/9/2005 Francisco Hoyos 21 Atributo WebMethod Pode vir acompanhado das seguintes propriedades: 27/9/2005 Description MessageName EnableSession CacheDuration TransactionOption BufferResponse Francisco Hoyos 22 WebMethod: Description, MessageName e EnableSession Description: Descrição textual da operação. Aparece no WSDL. MessageName: Nome pelo qual a operação é conhecida pelo cliente. Aparece no WSDL. EnableSession: Se true, o serviço tem acesso aos objetos que mantêm o estado da sessão com cada cliente. 27/9/2005 Francisco Hoyos 23 WebMethod: CacheDuration CacheDuration: Especifica o tempo em segundos que o resultado de uma operação será armazenado na memória. O resultado é mantido na forma de um par request/response. Novos pedidos de execução da mesma operação, com os mesmos parâmetros, serão respondidos com dados diretamente do cache, sem a invocação do serviço. 27/9/2005 Francisco Hoyos 24 WebMethod: TransactionOption e BufferResponse TransactionOption: Permite especificar que o web method seja executado numa transação. A transação é interrompida quando uma exceção é lançada ou quando o método SetAbort da classe System.EnterpriseServices.ContextUtil é chamado. BufferResponse: Se true, a resposta do serviço é inteiramente armazenada antes de ser enviada ao cliente, ao invés de ser enviada em várias pequenas partes. 27/9/2005 Francisco Hoyos 25 A classe WebService using System.Web.Services; public class MathService : System.Web.Services.WebService { [WebMethod] public double Add(double x, double y) { return x + y; } } Se o serviço especificar WebService como classe base, ele ganha acesso a objetos ASP.NET, tais como Application, Session, User e Context, que oferecem facilidades para gerenciamento de sessão e identificação do usuário do serviço. 27/9/2005 Francisco Hoyos 26 .NET WS: exemplo using System; using System.Web.Services; public class Point { public double x; public double y; } [WebService(Namespace="urn:geometry")] public class Geometry { [WebMethod] public double Distance(Point orig, Point dest) { return Math.Sqrt(Math.Pow(orig.x-dest.x, 2) + Math.Pow(orig.y-dest.y, 2)); } } 27/9/2005 Francisco Hoyos 27 .NET WS: SOAP request <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <Distance xmlns="urn:geometry"> <orig> <x>0</x> <y>0</y> </orig> <dest> <x>3</x> <y>4</y> </dest> </Distance> </soap:Body> </soap:Envelope> 27/9/2005 Francisco Hoyos 28 .NET WS: SOAP response <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <DistanceResponse xmlns="urn:geometry"> <DistanceResult>5</DistanceResult> </DistanceResponse> </soap:Body> </soap:Envelope> 27/9/2005 Francisco Hoyos 29 .NET WS: uso de atributos using System; using System.Web.Services; using System.Web.Services.Protocols; using System.Xml.Serialization; public class Point { [XmlAttribute] public double x; [XmlAttribute] public double y; } [WebService(Namespace="urn:geometry")] public class Geometry { [WebMethod] [SoapDocumentMethod(RequestElementName="CalcDistance", ResponseElementName="CalculatedDistance")] [return: XmlElement("result")] public double Distance([XmlElement("o")] Point orig, [XmlElement("d")] Point dest) { return Math.Sqrt(Math.Pow(orig.x-dest.x, 2) + Math.Pow(orig.y-dest.y, 2)); } } 27/9/2005 Francisco Hoyos 30 SOAP request resultante <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <CalcDistance xmlns="urn:geometry"> <o x=“0” y=“0” /> <d x=“3” y=“4” /> </CalcDistance> </soap:Body> </soap:Envelope> 27/9/2005 Francisco Hoyos 31 SOAP response resultante <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <CalculatedDistance xmlns="urn:geometry"> <result>5</result> </CalculatedDistance> </soap:Body> </soap:Envelope> 27/9/2005 Francisco Hoyos 32 Acessando o SOAP header 1 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Header> <x:UsernameToken xmlns:x="http://example.org/security"> <username>Mary</username> <password>yraM</password> </x:UsernameToken> </soap:Header> <soap:Body> <CalcDistance xmlns="urn:geometry"> ... 27/9/2005 Francisco Hoyos 33 Acessando o SOAP header 2 Criar uma classe .NET que representa o tipo do elemento desejado no header, conforme o XML Schema [XmlType(Namespace="http://example.org/security")] [XmlRoot(Namespace="http://example.org/security")] public class UsernameToken : SoapHeader { public string username; public string password; } 27/9/2005 Francisco Hoyos 34 Acessando o SOAP header 3 using System; using System.Web.Services; using System.Web.Services.Protocols; [WebService(Namespace="urn:geometry")] public class Geometry { public UsernameToken Token; [WebMethod] [SoapHeader("Token")] public double Distance(Point orig, Point dest) { if (!Token.username.Equals(Reverse(Token.password))) throw new Exception("access denied"); return Math.Sqrt(Math.Pow(orig.x-dest.x, 2) + Math.Pow(orig.y-dest.y, 2)); } } 27/9/2005 Francisco Hoyos 35 Cliente “na raça” Montar mensagem SOAP “manualmente”, usando uma biblioteca XML Enviar mensagem via HTTP Receber resposta SOAP via HTTP Usar XML parser para obter valor de retorno incluído na resposta 27/9/2005 Francisco Hoyos 36 .NET WS: cliente O consumo de serviços web em .NET é feito através de classes proxy. O programa wsdl.exe gera uma classe proxy a partir do WSDL do serviço. Entre outras opções, wsdl.exe permite selecionar a linguagem de programação em que o proxy é implementado. Visual Studio .NET gera automaticamente a classe proxy através da opção “Add Web Reference”. 27/9/2005 Francisco Hoyos 37 Adicionando uma Web Reference 1 27/9/2005 Francisco Hoyos 38 Adicionando uma Web Reference 2 27/9/2005 Francisco Hoyos 39 Adicionando uma Web Reference 3 27/9/2005 Francisco Hoyos 40 Usando a classe proxy private void Submit1_Click(object sender, System.EventArgs e) { Simple1.TryThisOut svc1 = new Simple1.TryThisOut(); SvcOutput1.Text = svc1.WakeUp(SvcInput1.Text); } 27/9/2005 Francisco Hoyos 41 .NET WS: invocação assíncrona de serviços Para cada operação XYZ do serviço são gerados dois métodos para invocação assíncrona: 27/9/2005 BeginXYZ(): invoca XYZ sem aguardar pela resposta, retornando ao chamador imediatamente. EndXYZ(): retorna o resultado da invocação a XYZ. Francisco Hoyos 42 .NET WS: invocação assíncrona, polling static IAsyncResult tempHolder1; WeatherFetcher.USWeather USW = new WeatherFetcher.USWeather( ); private void Button1_Click(object sender, System.EventArgs e) { Button1.Enabled = false; tempHolder1 = USW.BeginGetWeatherReport(TextBox1.Text, null, null); } private void Button2_Click(object sender, System.EventArgs e) { if (tempHolder1.IsCompleted) { Label2.Text += USW.EndGetWeatherReport(tempHolder1) + "<br>"; Button1.Enabled = true; tempHolder1 = null; } else { Label2.Text += "1 is Still completing..."; } } 27/9/2005 Francisco Hoyos 43 .NET WS: invocação assíncrona, callback private void Button1_Click(object sender, System.EventArgs e) { Button1.Enabled = false; AsyncCallback callBack = new AsyncCallback(MyCallBack); USW.BeginGetWeatherReport(TextBox1.Text, callBack, USW); Label2.Text = "Web Service called..."; } public void MyCallBack(IAsyncResult AsyncResult) { string ReturnValue; ReturnValue = USW.EndGetWeatherReport(AsyncResult); Label2.Text += "<br>" + "Weather Report = " + ReturnValue; Button1.Enabled = true; } 27/9/2005 Francisco Hoyos 44 J2EE Plataforma para o desenvolvimento de aplicações para o meio empresarial Antecede web services J2EE 1.4 foi a primeira versão a adotar completamente o paradigma de web services 27/9/2005 Francisco Hoyos 45 J2EE: plataforma 27/9/2005 Francisco Hoyos 46 J2EE 1.4: APIs 27/9/2005 Francisco Hoyos 47 J2EE 1.4 Preocupação com interoperabilidade: adoção do Basic Profile (BP), publicado pela Web Services Interoperability Organization (WS-I) (www.ws-i.org). BP especifica como usar XML, WSDL, SOAP e UDDI conjuntamente, eliminando ambigüidades. 27/9/2005 Francisco Hoyos 48 J2EE Web Service APIs JAX-RPC (Java API for XML-based RPC): permite a criação (servidor) e consumo (cliente) de web services SAAJ (SOAP with Attachments API for Java): usada na criação e manipulação baixo nível de mensagens SOAP JAXR (Java API for XML Registries): acesso aos “catálogos” UDDI JAXP (JAVA API for XML Processing): junto com DOM e SAX, permite a manipulação de documentos XML 27/9/2005 Francisco Hoyos 49 JAX-RPC: servidor Existem dois modelos de programação: 27/9/2005 JAX-RPC Service Endpoint (JSE): mais simples, baseado em servlet containers Enterprise Java Beans (EJB) endpoint: baseado em stateless EJBs Francisco Hoyos 50 JAX-RPC: JSE Para criar um JSE basta definir: 27/9/2005 uma endpoint interface, com as operações do serviço web uma classe que implementa a interface acima Francisco Hoyos 51 JAX-RPC: JSE - exemplo public interface BookQuote extends java.rmi.Remote { public float getBookPrice(String isbn) throws java.rmi.RemoteException; } public class BookQuote_Impl_1 implements BookQuote { public float getBookPrice(String isbn) { return 24.99f; } } 27/9/2005 Francisco Hoyos 52 JAX-RPC: JSE - execução 27/9/2005 Francisco Hoyos 53 JAX-RPC: JSE e servlets O JSE é parte do servlet, ou seja, para todos os fins práticos, o JSE é o servlet. Assim, o JSE tem acesso a todos os recursos aos quais um servlet tem via o JNDI Environment Naming Context (ENC). Tais recursos incluem JDBC drivers, JMS providers, EJBs, J2EE connectors, outros serviços web, variáveis de ambiente, o ServletContext e a HttpSession. 27/9/2005 Francisco Hoyos 54 public class BookQuote_Impl_2 implements BookQuote { public float getBookPrice(String isbn) { java.sql.Connection jdbcConnection = null; java.sql.Statement sqlStatement = null; java.sql.ResultSet resultSet; try { javax.naming.InitialContext jndiEnc = new javax.naming.InitialContext(); javax.sql.DataSource dataSource = (javax.sql.DataSource) jndiEnc.lookup("java:comp/env/jdbc/DataSource"); jdbcConnection = dataSource.getConnection(); sqlStatement = jdbcConnection.createStatement(); resultSet = sqlStatement.executeQuery("SELECT wholesale FROM CATALOG WHERE isbn = \'" + isbn + "\'"); if (resultSet.next( )) { float price = resultSet.getFloat("wholesale"); return price; } return 0; // zero means it's not stocked. } catch (java.sql.SQLException se) { ... } catch (javax.naming.NamingException ne) { ... } } } 27/9/2005 Francisco Hoyos 55 JSE: interface ServiceLifecycle O JSE pode implementar opcionalmente a interface ServiceLifecycle. Ela define os métodos init() e destroy(), invocados no início e final, respectivamente, da vida do JSE. O JSE recebe via init() uma referência ao ServletEndpointContext, que por sua vez dá acesso a uma série de outros recursos. 27/9/2005 Francisco Hoyos 56 JSE: exemplo ServiceLifecycle public class BookQuote_Impl_5 implements BookQuote, ServiceLifecycle { javax.sql.DataSource dataSource; ServletEndpointContext endPtCntxt; public void init(Object context) throws ServiceException { try { endPtCntxt = (ServletEndpointContext) context; InitialContext jndiEnc = new InitialContext(); javax.sql.DataSource dataSource = (javax.sql.DataSource) jndiEnc.lookup("java:comp/env/jdbc/BookDatabase"); } catch(NamingException ne) { throw new ServiceException("Cannot init JNDI ENC", ne); } } } 27/9/2005 Francisco Hoyos 57 JSE: ServletEndpointContext 1 Faz a interface do JSE com o seu servlet container. Para ser usado, a referência recebida deve ser armazenada numa variável do JSE. 27/9/2005 Francisco Hoyos 58 JSE: ServletEndpointContext 2 package javax.xml.rpc.server; public interface ServletEndpointContext { public java.security.Principal getUserPrincipal(); public boolean isUserInRole(String role); public javax.xml.rpc.handler.MessageContext getMessageContext(); public javax.Servlet.http.HttpSession getHttpSession() throws javax.xml.rpc.JAXRPCException; public javax.Servlet.ServletContext getServletContext(); } 27/9/2005 Francisco Hoyos 59 JSE: getUserPrincipal(), isUserInRole() O objeto Principal representa a identidade da aplicação cliente, que está enviando o request SOAP. Disponível apenas se o JSE for configurado para usar HTTP Basic Authentication (BASICAUTH) ou Symmetric HTTP. “Papéis” (roles) podem ser atribuídos a Principals usando ferramentas específicas do fornecedor J2EE. O JSE verifica qual o papel do cliente através do isUserInRole(). 27/9/2005 Francisco Hoyos 60 JSE: getHttpSession() Usado para obter um objeto HttpSession que representa a sessão HTTP associada com o cliente SOAP. A sessão HTTP permite ao servlet container associar múltiplos requests HTTP com um cliente SOAP específico. O controle de sessão HTTP é feito normalmente via cookies ou SSL. 27/9/2005 Francisco Hoyos 61 JSE: HttpSession O objeto HttpSession permite ao JSE ver e modificar informações da sessão, tais como o identificador da sessão, hora de criação, hora do último acesso e quando a sessão vai expirar. Além disso, o JSE pode associar atributos arbitrários com uma sessão, mantendo estado entre invocações feitas por um mesmo cliente. Um atributo é um par “nome-valor”. 27/9/2005 Francisco Hoyos 62 JSE: getServletContext() Usado para obter o objeto ServletContext do servlet JAX-RPC que encapsula a instância JSE. O ServletContext permite acesso a: 27/9/2005 atributos “nome-valor” parâmetros de inicialização arquivos, tipos MIME, conversões path-URL fornecedor e versão do container logging RequestDispatcher (permite chamadas a outro servlet, JSP ou página HTML) Francisco Hoyos 63 JSE: getMessageContext() Retorna um objeto MessageContext que é usado para compartilhar informações entre objetos handler e o objeto JSE. Message handlers permitem pré e pós processamento das mensagens SOAP trocadas entre “J2EE port components” (JSEs e endpoints EJB) e clientes SOAP. 27/9/2005 Francisco Hoyos 64 JAX-RPC: EJB web services 1 Recomendado para serviços web que exigem alto uso de transações, pois o sistema de containers dos EJBs garante automaticamente execução transacional. alteração de dados via JDBC e/ou JMS coordenação das atividades de outros EJBs, que por sua vez modificam dados “Usar um EJB como um endpoint para serviço web pode ser como usar uma marreta para bater um prego” [1] 27/9/2005 Francisco Hoyos 65 JAX-RPC: EJB web services 2 Implementado num stateless session bean, inclusive um já existente (para expor seus métodos como serviços web). Teoricamente um mesmo stateless session bean pode simultaneamente atender clientes do tipo remote, local e endpoint (serviço web). Um EJB endpoint não tem uma home interface. 27/9/2005 Francisco Hoyos 66 JAX-RPC: EJB web services 3 Para criar um EJB endpoint basta definir: 27/9/2005 uma endpoint interface, com as operações do serviço web (exatamente como no caso de um JSE) uma classe bean que implementa as operações do serviço definido pela interface acima (não é necessário implementar a interface propriamente dita) Francisco Hoyos 67 EJB: classe bean - exemplo public class BookQuoteBean_1 implements javax.ejb.SessionBean { SessionContext ejbContext; public void ejbCreate( ) { } public float getBookPrice(String isbn) { return 24.99f; } public void setSessionContext(SessionContext cntxt) { ejbContext = cntxt; } public void ejbActivate( ) { } public void ejbPassivate( ) { } public void ejbRemove( ) { } } 27/9/2005 Francisco Hoyos 68 EJB: a interface SessionBean Toda classe stateless session bean deve implementar a interface javax.ejb.SessionBean, usada pelo container para controlar o ciclo de vida do bean. public interface SessionBean extends javax.ejb.EnterpriseBean { public void setSessionContext(SessionContext cntxt); public void ejbActivate( ); public void ejbPassivate( ); public void ejbRemove( ); } 27/9/2005 Francisco Hoyos 69 EJB: ciclo de vida do bean Uma vez colocado no “method-ready pool”, o bean está pronto para atender pedidos de clientes. 27/9/2005 Francisco Hoyos 70 EJB: atendendo requisições SOAP Quando o container EJB recebe uma mensagem SOAP, ele identifica a classe EJB apropriada para aquela requisição e seleciona uma instância daquele EJB do method-ready pool. A chamada SOAP é mapeada no método correspondente da instância. Após o retorno do método, o bean volta para o pool. Uma instância stateless não deve manter estado específico de um cliente entre invocações de seus métodos, pois cada requisição pode vir de um cliente diferente. 27/9/2005 Francisco Hoyos 71 EJB: ambiente de execução Assim como o JSE, um EJB pode acessar recursos, outros EJBs e serviços web através de seu JNDI ENC. Transações e segurança são gerenciadas automaticamente pelo sistema de container de EJBs. 27/9/2005 Francisco Hoyos 72 EJB: SessionContext 1 Recebido pelo EJB através do método setSessionContext(). Normalmente armazenado numa variável do EJB para uso posterior. A interface SessionContext é implementada pelo container. 27/9/2005 Francisco Hoyos 73 EJB: SessionContext 2 public interface SessionContext extends EJBContext { public EJBLocalObject getEJBLocalObject(); public public public public EJBObject getEJBObject(); EJBLocalHome getEJBLocalHome(); EJBHome getEJBHome(); Principal getCallerPrincipal(); public public public public public boolean isCallerInRole(String roleName); UserTransaction getUserTransaction(); boolean getRollbackOnly(); void setRollbackOnly(); MessageContext getMessageContext(); public TimerService getTimerService(); } 27/9/2005 Francisco Hoyos 74 JAX-RPC: cliente As três formas abaixo podem ser usadas por um cliente Java para acessar um serviço web: 27/9/2005 stub proxy dinâmico DII (Dynamic Invocation Interface) Francisco Hoyos 75 JAX-RPC: stubs 1 O stub permite que o acesso ao serviço web seja feito via uma simples chamada a um método de um objeto Java local. O compilador JAX-RPC gera a partir do WSDL do serviço: 27/9/2005 interface endpoint classe stub (opcionalmente) interface do serviço (“factory de stubs”) Francisco Hoyos 76 JAX-RPC: stubs 2 A interface endpoint é equivalente à interface de mesmo nome usada no lado do servidor para implementar o serviço web. A classe stub implementa a interface endpoint. A classe stub também implementa a interface javax.xml.rpc.Stub. 27/9/2005 Francisco Hoyos 77 public interface Stub { // Std property: The Web service's Internet address. public static String ENDPOINT_ADDRESS_PROPERTY; // Std public // Std public // Std property: Password for authentication. static String PASSWORD_PROPERTY; property: User name for authentication. static String USERNAME_PROPERTY; prop.: Boolean flag for maintaining an HTTP session. public static String SESSION_MAINTAIN_PROPERTY; // Given a property name, get its value. public Object _getProperty(java.lang.String name); // Get the names of all the properties the stub supports. public Iterator _getPropertyNames(); // Configure a property on the stub. public void _setProperty(java.lang.String name, java.lang.Object value); } 27/9/2005 Francisco Hoyos 78 Cliente WS: “service interface” O compilador JAX-RPC pode gerar uma interface, juntamente com uma classe que a implementa, que dá acesso a objetos stub. Uma instância da classe que implementa a service interface é responsável por criar e pré-configurar os stubs requisitados pelo cliente. 27/9/2005 Francisco Hoyos 79 Cliente WS: Usando um stub public class BookQuoteServlet_1 extends javax.servlet.http.HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,java.io.IOException { try { String isbn = req.getParameter("isbn"); InitialContext jndiContext = new InitialContext(); BookQuoteService service = (BookQuoteService) jndiContext.lookup("java:comp/env/service/BookQuoteService"); BookQuote bookQuote = service.getBookQuotePort(); float price = bookQuote.getBookPrice(isbn); java.io.Writer outStream = resp.getWriter(); outStream.write("<html><body>The wholesale price for ISBN:" + isbn + " = " + price + "</body></html>"); } catch ... 27/9/2005 Francisco Hoyos 80 Cliente WS: execução Quando um método do stub é invocado, o stub converte a chamada numa mensagem SOAP e a envia ao servidor (o Basic Profile requer o uso de HTTP POST). Quando o stub recebe a mensagem SOAP de resposta, ele extrai o valor de retorno. Se a mensagem contém uma indicação de falha, o stub lança uma exceção Java apropriada. 27/9/2005 Francisco Hoyos 81 Usando um stub a partir de J2SE public class JaxRpcExample_1 { public static void main(String[] args) throws Exception { String isbn = args[0]; BookQuoteService service = (BookQuoteService) ServiceFactory.loadService( com.jwsbook.jaxrpc.BookQuoteService.class); BookQuote bookQuote = service.getBookQuotePort(); float price = bookQuote.getBookPrice(isbn); System.out.println("The price is = " + price); } } 27/9/2005 Francisco Hoyos 82 Proxy dinâmico (cliente J2EE) public class JaxRpcExample_2 { public static void main(String[] args) throws Exception { String isbn = args[0]; InitialContext jndiContext = new InitialContext(); javax.xml.rpc.Service service = (javax.xml.rpc.Service) jndiContext.lookup("java:comp/env/service/Service"); BookQuote BookQuote_proxy = (BookQuote) service.getPort(BookQuote.class); float price = BookQuote_proxy.getBookPrice(isbn); System.out.println("The price is = " + price); } } 27/9/2005 Francisco Hoyos 83 Proxy dinâmico Um elemento service-ref deve ser incluído no “deployment descriptor” para que o J2EE container encontre o WSDL. <service-ref xmlns:mh="http://www.mh.com/jwsbook/BookQuote"> <service-ref-name>service/Service</service-ref-name> <service-interface>javax.xml.rpc.Service</service-interface> <wsdl-file>BookQuote.wsdl</wsdl-file> <service-qname>mh:BookQuoteService</service-qname> </service-ref> 27/9/2005 Francisco Hoyos 84 Dynamic Invocation Interface API genérica para invocação de serviços web. Não requer uma endpoint interface (que é específica por serviço). Pode ser usada por aplicações que descobrem e invocam serviços web automaticamente. 27/9/2005 Francisco Hoyos 85 public class JaxRpcExample_4 { public static void main(String[] args) throws Exception { String isbn = args[0]; InitialContext jndiContext = new InitialContext(); javax.xml.rpc.Service service = (javax.xml.rpc.Service) jndiContext.lookup("java:comp/env/service/Service"); QName portName = new QName( "http://www.M-H.com/jwsbook/BookQuote", "BookQuotePort"); QName operationName = new QName( "http://www.M-H.com/jwsbook/BookQuote", "getBookPrice"); Call call = service.createCall(portName, operationName); Object[] inputParams = new Object[] {isbn}; Float price = (Float) call.invoke(inputParams); System.out.println("The price is = " +price.floatValue()); } } 27/9/2005 Francisco Hoyos 86 J2EE Web Services 27/9/2005 Francisco Hoyos 87 J2EE x .NET Tecnologia J2EE .NET Linguagem, runtime Java, JVM várias, CLR Deployment Java package Assembly Aplicações web JSP, servlets ASP.NET Servidor web vários Microsoft IIS Componentes EJB COM+ Bancos de dados JDBC ADO.NET Mensagens JMS System.Messaging Integração com EIS JCA Host Integration Server Remoting RMI / IIOP .NET Remoting Serviço de nomes JNDI Active Directory 27/9/2005 Francisco Hoyos 88 27/9/2005 Francisco Hoyos 89 27/9/2005 Francisco Hoyos 90 Considerações finais 1 Java: linguagem única suportada por várias plataformas. .NET: plataforma única que suporta várias linguagens. Muito fácil expor métodos de classes .NET como serviços web, às custas de uma certa “poluição” da sintaxe das linguagens. Visual Studio .NET é uma solução completa para desenvolvimento e consumo de serviços web, totalmente baseada em interface gráfica. => aumento de produtividade 27/9/2005 Francisco Hoyos 91 Considerações finais 2 J2EE é uma plataforma mais madura que .NET. Modelo EJB é complexo, mas poderoso. Não existe algo equivalente em .NET. Google Web API: para .NET, nada além do WSDL é oferecido; para Java, uma API especial é disponibilizada. 27/9/2005 Francisco Hoyos 92 Referências [1] J2EE Web Services; Richard Monson-Haefel; Addison Wesley; 2003 [2] Programming Microsoft .NET XML Web Services; Damien Foggon, Daniel Maharry, Chris Ullman, Karli Watson; Microsoft Press; 2004 [3] Introducing Microsoft .NET, Third Edition; David S. Platt; Microsoft Press; 2003 [4] informit.com’s .NET Reference Guide, http://www.informit.com/guides/guide.asp?g=dotnet [5] How ASP.NET Web Services Work, Aaron Skonnard, http://www.msdn.microsoft.com/webservices [6] ASP.net QuickStart Tutorial, http://samples.gotdotnet.com/quickstart/aspplus 27/9/2005 Francisco Hoyos 93