Resumo Anotacoes JAX-WS Certificacao SCDJWS 5
-
Upload
gilberto-holms -
Category
Documents
-
view
2.056 -
download
29
description
Transcript of Resumo Anotacoes JAX-WS Certificacao SCDJWS 5
Gilberto Holms http://gibaholms.wordpress.com/
Resumo Anotações JAX-WS para Certificação SCDJWS 5. 0 Gilberto Augusto Holms @gibaholms [email protected] http://gibaholms.wordpress.com/ Modos de Criar um WebService
• WSDL-to-Java Aproach: wsimport • Java-to-WSDL Aproach: apt / wsgen
Tools
• apt o Entrada � códigos-fonte (.java) da SEI Implementation o Saída � Portable Artifacts (SEI + Service + JAXB Types + Faults)
• wsgen o Entrada � classe (.class) da SEI Implementation o Saída � WSDL e Portable Artifacts
• wsimport o Entrada � documento WSDL o Saída � Portable Artifacts (SEI + Service + JAXB Types + Faults)
@WebService
• Exemplo de SEI em Servlet: @WebService public class Calculator { public int add( int a, int b) { return a + b; } }
• Exemplo de SEI em EJB: @WebService @Stateless public class Calculator { @Resource private WebServiceContext context ; public int add( int a, int b) { return a + b; } }
• Utilizando SEI em interface separada:
@WebService public interface CalculatorEndpoint { public int add( int a, int b); } @WebService( endpointInterface = "com.example.CalculatorEndpoint" ) public class Calculator implements CalculatorEndpoint { public int add( int a, int b) { return a + b;
Gilberto Holms http://gibaholms.wordpress.com/
} }
• Métodos expostos como operações do serviço: o Sem SEI separada, todos os métodos públicos são expostos o Com SEI separada, apenas os métodos da interface SEI são expostos o Se houverem métodos anotados com @WebMethod , apenas estes serão expostos
• Se utilizada SEI separada, a classe de serviço não pode definir o parâmetro @WebService.name • As classes/interfaces SEI podem, mas não precisam extender java.rmi.Remote • As classes de serviço precisam fornecer construtor default • As classes de serviço podem utilizar as anotações @PostConstruct e @PreDestroy • Os métodos podem, mas não precisam lançar java.rmi.RemoteException • Atributos de @WebService:
o name � nome do wsdl:portType � Valor default: nome abreviado da classe
o targetNamespace � targetNamespace do WSDL, que será atribuído aos itens do WSDL � Valor default: package da classe � Se utilizado numa SEI, afeta apenas wsdl:portType � Se utilizado num serviço com SEI separada, afeta apenas wsdl:service � Se utilizado num serviço sem SEI separada, afeta wsdl:portType e wsdl:service
o serviceName � nome do wsdl:service � Proibido usar na interface SEI � Valor default: nome da classe + “Service”
o portName � nome do wsdl:port � Proibido usar na interface SEI � Valor default: @WebService.name + “Port”
o endpointInterface � para usar interface SEI separada, setar o nome completo dela aqui � Proibido usar na interface SEI, vale apenas para a classe de serviço
o wsdlLocation � para criar o serviço através de um WSDL pré-existente @WebMethod
• Exemplo: @Stateless @WebService(name = "TravelAgent" ) public class TravelAgentBean { @WebMethod(operationName = "Reserve" ) public String makeReservation( int cruiseId) { // implementation } }
• Customiza uma operação do serviço • Os métodos anotados com @WebMethod precisam ser public • Os métodos anotados não podem ser static nem final • Atributos de @WebMethod
o operationName � nome do wsdl:operation � Valor default: nome do método java
o action � nome da SOAPAction que constará no WSDL (apenas para bindings tipo SOAP) � Valor default: string vazia “” � WSDL: <soap:operation soapAction=”xxx”/>
o exclude � não expõe o método no WebService � Pode anular um @WebMethod herdado de uma superclasse � Não pode ser usado em uma interface SEI
@SOAPBinding
• Exemplo: @WebService @SOAPBinding(
Gilberto Holms http://gibaholms.wordpress.com/
style = SOAPBinding.Style.RPC, use = SOAPBinding.Use.LITERAL ) public class ExampleService { @WebMethod public int add( int a, int b) { return a + b; } }
• Customiza o tipo de binding do serviço • Atributos de @SOAPBinding:
o style � estilo da mensagem (DOCUMENT ou RPC) � Valor default: DOCUMENT
o use � tipo de encoding (LITERAL ou ENCODED) � Valor default: LITERAL � O uso do tipo ENCODED é proibido pelo Basic Profile 1.1
o parameterStyle � como os parâmetros serão montados (BARE ou WRAPPED) � Valor default: WRAPPED
• Possíveis combinações: Style Use ParameterStyle Descrição
RPC LITERAL <n/a> Cada parâmetro é mapeado para uma wsdl:part, que pertence a um schema (padrão RPC/Literal)
DOCUMENT LITERAL BARE Permite apenas um elemento como parâmetro, que é o root-element de um schema (padrão Document/Literal)
DOCUMENT LITERAL WRAPPED
Agrupa diversos parâmetros dentro de um elemento root com o mesmo nome da wsdl:operation (“forja” um padrão Document/Literal mesmo quando é setado mais de elemento como parâmetro)
@WebParam
• Exemplo: @WebService @SOAPBinding( style = SOAPBinding.Style.RPC ) public class PingService { @WebMethod(operationName = "PingTwoWay" ) public void ping( @WebParam(mode = WebParam.Mode.INOUT) Holder<PingDoc ument> ping) { // implementation } @WebMethod(operationName = "SecurePing" ) public void ping(PingDocument ping, @WebParam(header = true) SecurityHeader secHeader) { // implementation } }
• Customiza o mapeamento de um parâmetro para uma message part • Holder types: javax.xml.ws.Holder<Object> • Atributos de @WebParam:
o name � nome do parâmetro � Se for RPC/Literal e não foi definido @WebParam.partName, define o nome do
wsdl:part � Se for Document/Literal ou um header block, define o nome local do elemento que
representa o parâmetro � É obrigatório quando for Document/ BARE e quando mode for OUT ou INOUT � Valor default: @WebMethod.operationName para Document/BARE e nome do
argumento java para demais casos o partName � nome do wsdl:part
� É utilizado apenas para estilos RPC e Document/BARE � Valor default: @WebParam.name
o targetNamespace � namespace do parâmetro � Usado apenas para Document/Literal ou se a part representa um header block
o mode � tipo de parâmetro (IN, OUT ou INOUT)
Gilberto Holms http://gibaholms.wordpress.com/
� Permitido OUT e INOUT apenas para Holder types � Valor default: normalmente IN, ou INOUT se for um Holder type
o header � booleano indicando se a part representa um header block � Valor default: false
@WebResult
• Exemplo: @WebService public class CustomerService { @WebMethod @WebResult(name = "CustomerRecord" ) public CustomerRecord locateCustomer( @WebParam(name = "FirstName" ) String firstName, @WebParam(name = "LastName" ) String lastName, @WebParam(name = "Address" ) USAddress addr) { // implementation } }
• Customiza o mapeamento de um valor de retorno para uma message part • É sempre a message part que não aparece no parameterOrder, ou seja, é o retorno geral do response
do operação • Atributos de @WebResult:
o name � nome do valor de retorno � Se for RPC/Literal e não foi definido @WebParam.partName, define o nome do
wsdl:part do retorno � Se for Document/Literal ou um retorno de header block, define o nome local do
elemento que representa � Valor default: @WebMethod.operationName + “Response” para Document/BARE e
“return” para demais casos o partName � nome do wsdl:part
� É utilizado apenas para estilos RPC e Document/BARE � Valor default: @WebResult.name
o targetNamespace � namespace do retorno � Usado apenas para Document/Literal ou se a part representa um header block
o header � booleano indicando se a part representa um retorno de header block � Valor default: false
@OneWay
• Exemplo: @WebService public class PingService { @WebMethod @Oneway public void ping() { // implementation } }
• Define que trata-se de uma mensagem one-way, ou seja, omite a tag output da operation do WSDL • Os métodos one-way:
o Precisam retornar void o Não podem lançar exceções verificadas o Não podem ter parâmetros Holder types
@SOAPMessageHandlers
• Não deve ser utilizada, pois foi “deprecated” a partir da versão 2.0 da JAX-WS • No lugar dela, deve-se utilizar @HandlerChain
Gilberto Holms http://gibaholms.wordpress.com/
WebServiceContext
• Exemplo: @WebService public class Teste { @Resource private WebServiceContext context ; public void checkOut( int orderId) { MessageContext messageCtx = context .getMessageContext(); SOAPMessageContext soapMessageCtx = (SOAPMessageC ontext)messageCtx; SOAPMessage message = soapMessageCtx.getMessage(); } }
• É um objeto de contexto obtido por injeção de dependência • Fornece acesso ao contexto em que se encontra (Servlet ou EJB) • Principais métodos de WebServiceContext:
o getUserPrincipal o isUserInRole o getMessageContext
• MessageContext � é uma “property-bag”, um Map<String, Object> contendo referências a diversas variáveis do contexto em que se encontra (javax.servlet.http.HttpServletRequest, Http Request Headers, Query String, etc)
• Se for um serviço do tipo SOAP, contém uma instância de SOAPMessageContext, onde podemos obter, por exemplo, a representação SAAJ da mensagem
@WebServiceProvider
• Exemplo de um Provider SOAP: @WebServiceProvider (portName = "stockQuoteReporterPort" , serviceName = "stockQuoteReporter" ) @ServiceMode (value = Service .Mode.MESSAGE) public class stockQuoteReporterProvider implements Provider <SOAPMessage> { public SOAPMessage invoke(SOAPMessage request) { SOAPBody requestBody = request.getSOAPBody(); if(requestBody.getElementName.getLocalName.equals( "getStockPrice" )) { MessageFactory mf = MessageFactory .newInstance(); SOAPFactory sf = SOAPFactory .newInstance(); SOAPMessage response = mf.createMessage(); SOAPBody respBody = response.getSOAPBody(); Name bodyName = sf.createName( "getStockPriceResponse" ); respBody.addBodyElement(bodyName); SOAPElement respContent = respBody.addChildElement( "price" ); respContent.setValue( "123.00" ); response.saveChanges(); return response; } } }
• Exemplo de um Provider HTTP (RESTful):
@WebServiceProvider(targetNamespace = "http://example.org" , serviceName = "NearbyCityService" ) @BindingType(value = HTTPBinding.HTTP_BINDING) public class NearbyCity implements Provider<Source> { @Resource private WebServiceContext wsContext ; public Source invoke(Source source) { try { MessageContext messageContext = wsContext .getMessageContext(); String query = (String) messageContext.get(Messa geContext.QUERY_STRING); if (query != null && query.contains( "lat=" ) && query.contains( "long=" )) { return createSource(query); // cria mensagem via JAXP } else { throw new HTTPException(404); } } catch (Exception e) { throw new HTTPException(500); }
Gilberto Holms http://gibaholms.wordpress.com/
} }
• Não pode ser usada junto com a anotação @WebService • Permite criar um serviço sem SEI, capaz de receber e responder qualquer tipo de XML, manipulando a
mensagem em baixo nível através de SAAJ ou JAXP • Útil para criar serviços RESTful baseados em XML • Podemos utilizar uma extensão para utilizar RESTful baseado em JSON :
o @BindingType(JSONBindingID.JSON_BINDING) • Anotação @BindingType:
o Indica o tipo de binding (protocolo de aplicação) que será utilizado o Principais tipos:
� SOAPBinding.SOAP11HTTP_BINDING � mensagem SOAP 1.1 � SOAPBinding.SOAP12HTTP_BINDING � mensagem SOAP 1.2 � HTTPBinding.HTTP_BINDING � mensagem HTTP POST
• Anotação @ServiceMode: o Indica a forma como a mensagem será recebida no método invoke o Varia de acordo com o tipo de binding o Tipos permitidos:
� Service.Mode.MESSAGE � XML contendo o protocolo completo da mensagem • Para SOAP, envia todo o soap:Envelope • Para HTTP, envia Http Headers e POST Payload
� Service.Message.PAYLOAD � XML apenas com o payload da mensagem • Para SOAP, envia apenas conteúdo do soap:Body • Para HTTP, envia apenas POST Payload
• Tipos de mensagem aceitas para T na interface Provider<T>: � javax.xml.transform.Source � objeto TrAX / SAX � javax.activation.DataSource � objeto JAF � javax.xml.soap.SOAPMessage � objeto SAAJ � Java.lang.Object � objeto JAXB
• Atributos de @WebServiceProvider: o targetNamespace � namespace do serviço o serviceName � nome do serviço (caso seja baseado em WSDL, representa wsdl:service) o portName � nome da porta (caso seja baseado em WSDL, representa wsdl:port) o wsdlLocation � para criar o serviço através de um WSDL pré-existente
@WebServiceRef
• Exemplo: public class JAXWSClient { @WebServiceRef( wsdlLocation = "http://localhost:8080/CalculatorService?WSDL" ) private CalculatorService calculatorService ; public void doTest() { Calculator port = calculatorService .getCalculatorPort(); int ret = port.add(2, 2); } }
• Container injeta um client de serviço através da sua classe Service • Permitido uso apenas no contexto JEE • Identico a tag do ejb-jar.xml: <web-service-ref> • Atributos de @WebServiceRef:
o name � nome que será gravado no JNDI-ENC o wsdlLocation � caminho para o WSDL
� Valor default: o mesmo informado na anotação @WebServiceClient da classe Service o mappedName � caminho JNDI global do recurso (fornecedor) o type � não precisa definir, é o atributo anotado o value � especifica o subtipo a ser injetado no atributo anotado
� Opcional se utilizado na classe Service
Gilberto Holms http://gibaholms.wordpress.com/
� Obrigatório se utilizado na interface SEI • Exemplos de uso de type e value:
// como a injeção é em Service impl, não precisa se tar o value @WebServiceRef private ProcessorService processorService ; // como a injeção é em SEI Interface, precisa setar o value (Service impl a usar) @WebServiceRef (ProcessorService. class) private Processor processorSEI ;
Tipos de JAX-WS Clients
• Tipos de Client: o Estático com Proxy Dinâmico
� Anotação @WebServiceClient o Dinâmico com Proxy Dinâmico
� Não utiliza anotações � Através das “factories” da classe javax.xml.ws.Service
o Cliente Dispatch � Totalmente dinâmico, pois trabalha a nível de XML (JAXP) � Utilizado para consumir serviços RESTful
• No JAX-WS, não existe a opção de gerar os stubs por ferramenta. Os stubs são gerados sempre dinamicamente, em tempo de execução, utilizando o recurso de Proxy Dinâmico do Java 5. Isto torna os clientes portáveis e tira a necessidade de re-gerar stubs sempre que mudar de fornecedor de container
Client Estático com Proxy Dinâmico
• Exemplo: @WebServiceClient( name = "ProcessorService" , targetNamespace = "http://charge-it.com/Processor" , wsdlLocation = "http://charge-it.com/Processor?wsdl" ) public class ProcessorService extends javax.xml.ws.Service { public ProcessorService() { super( new URL( "http://charge-it.com/Processor?wsdl" ), new QName( "http://charge-it.com/Processor" , "ProcessorService" ) ); } public ProcessorService(URL wsdlLocation, QName serviceNa me) { super(wsdlLocation, serviceName); } @WebEndpoint(name = "ProcessorPort" ) public Processor getProcessorPort() { return (Processor) super.getPort( new QName( "http://charge-it.com/Processor" , "ProcessorPort" ), Processor. class ); } }
• Os clients estáticos com proxy dinâmico:
o Precisam extender javax.xml.ws.Service o Devem fornecer dois construtores públicos:
� Construtor default: chamando super(URL, QName), que devem ser idênticos (equals) os valores da anotação @WebServiceClient
� Construtor: URL e QName, chamando super(URL, QName) o Devem fornecer um método @WebEndpoint para cada wsdl:port do serviço, chamando
super.getPort(QName, Class) onde o parâmetro class é a interface SEI • Atributos de @WebServiceClient:
o name � nome do wsdl:service que representa o targetNamespace � namespace do serviço
Gilberto Holms http://gibaholms.wordpress.com/
o wsdlLocation � endereço URL para o documento WSDL do WebService • Atributos de @WebEndpoint
o name � name do wsdl:port que representa Client Dinâmico com Proxy Dinâmico
• Exemplo: URL wsdlLocation = new URL( "http://example.org/my.wsdl" ); QName serviceName = new QName( "http://example.org/sample" , "ProcessorService" ); Service s = Service. create(wsdlLocation, serviceName); // informa o WSDL QName portName = new QName( "http://example.org/sample" , "ProcessorPort" ); Processor processorPort = s.getPort(portName, Proce ssor. class); processorPort.getPrice();
• Os clients dinâmicos com proxy dinâmico:
o Não utilizam anotações o Informam o WSDL o Não precisam extender javax.xml.ws.Service o Podem ser criados através da chamada Service.create(...) de duas maneiras:
� Informando o caminho do WSDL (mais comum) � Sem informar o WSDL (precisa setar outros parâmetros, pois o serviço não conhecerá
os schemas de request e response) Client Dinâmico com Dispatch
• Exemplo: URL wsdlLocation = new URL( "http://example.org/my.wsdl" ); QName serviceName = new QName( "http://example.org/sample" , "ProcessorService" ); Service s = Service. create(serviceName); // sem informar o WSDL Source requestMsg = ...; QName portName = ...; Dispatch<Source> disp = s.createDispatch(portName, Source. class, Service.Mode.PAYLOAD); Source responseMsg = disp.invoke(requestMsg);
• Os clients dinâmicos com dispatch:
o São muito utilizados para acessar serviços RESTful o Não precisam extender javax.xml.ws.Service o Podem operar em dois modos:
� Service.Mode.MESSAGE � XML contendo o protocolo completo da mensagem � Service.Message.PAYLOAD � XML apenas com o payload da mensagem
o Tipos de mensagem aceitas para T na interface Dispatch<T>: � javax.xml.transform.Source � objeto TrAX / SAX � javax.activation.DataSource � objeto JAF � javax.xml.soap.SOAPMessage � objeto SAAJ � Java.lang.Object � objeto JAXB
o Tipos de chamadas síncronas e assíncronas disponíveis: � T invoke(T msg) � Response<T> invokeAsync(T msg) � Future<?> invokeAsync(T msg, AsyncHandler<T> handler) � void invokeOneWay(T msg)
BindingProvider
• Exemplo: Service s = Service.create(...); Processor processorPort = s.getPort(portName, Proce ssor. class); BindingProvider bp = (BindingProvider)processorPort ; Map<String, Object> requestContext = bp.getRequestC ontext(); requestContext.put(BindingProvider.ENDPOINT_ADDRESS _PROPERTY, "http://blah/newendpoint" ); requestContext.setProperty( "javax.xml.ws.session.maintain" , Boolean.TRUE);
Gilberto Holms http://gibaholms.wordpress.com/
processorPort.getPrice(); Map<String, Object> responseContext = bp.getRespons eContext(); Integer responseCode = (Integer)responseContext.get (MessageContext.HTTP_RESPONSE_CODE);
• É uma API para obter o contexto da mensagem a partir do cliente • É uma “property-bag”, um Map<String, Object> contendo referências a diversas variáveis do contexto
da mensagem em que trabalha, tanto de request quanto response • Podemos, por exemplo, modificar a endpoint url do stub dinamicamente, setando a propriedade
“BindingProvider.ENDPOINT_ADDRESS_PROPERTY” • Principais métodos de BindingProvider:
o getRequestContext o getResponseContext o getBinding o getEndpointReference
APIs JavaSE 6
• Endpoint o Publica uma SEI Implementation (@WebService) em um servidor standalone (socket) JavaSE,
publicando automaticamente também o WSDL // Create and publish an endpoint Calculator calculator = new Calculator(); Endpoint endpoint = Endpoint.publish( "http://localhost/calculator" , calculator ); // Stop an endpoint endpoint.stop();
• Service o Cria um client standalone JavaSE para acessar um serviço
// Create a Service object CalculatorService svc = new CalculatorService(); // Create a proxy from the Service object Calculator proxy = svc.getCalculatorPort(); // Invoke a Web service operation int answer = proxy.add(35, 7);
Handler Framework
Gilberto Holms http://gibaholms.wordpress.com/
• Interface Handler<C extends MessageContext> o Subinterface LogicalHandler<L extends LogicalMessageContext>
� Define um handler independente de protocolo � LogicalMessage � LogicalMessageContext.getMessage()
• Trabalha com qualquer payload XML o Subinterface SOAPHandler<T extends SOAPMessageContext>
� Define um handler para mensagens SOAP � SOAPMessage � SOAPMessageContext.getMessage()
• Trabalha com uma mensagem SOAP (SAAJ API) • Exemplo de SOAPHandler
public class MySOAPHandler implements SOAPHandler <SOAPMessageContext > { public boolean handleMessage(SOAPMessageContext messageContext) { SOAPMessage msg = messageContext.getMessage(); // trata a mensagem via SAAJ return true; } }
• Aplicando Handlers no Client o 1 – Implementar HandlerResolver
� List<Handler> getHandlerChain(PortInfo) public class CardServiceHandlerResolver implements HandlerResolver { public List <Handler > getHandlerChain(PortInfo portInfo) { List <Handler > handlerChain = new ArrayList <Handler >(); ClientAuthenticationSOAPHandler authn = new ClientAuthenticationSOAPHandler (); EnvelopeLoggingSOAPHandler logging = new EnvelopeLoggingSOAPHandler (); JAXPPayloadLoggingLogicalHandler payload = new JAXPPayloadLoggingLogicalHandler (); QName serviceName = portInfo.getServiceName(); QName portName = portInfo.getPortName(); String bindingID = portInfo.getBindingID(); if (serviceName.getNamespaceURI().equals( "http://cardservice.handler.jaxws.company.com/servi ce" ) && serviceName.getLocalPart().equalsIgnoreCase( "CardService" )) { handlerChain.add(authn); handlerChain.add(logging); } if (bindingID.equals( "http://schemas.xmlsoap.org/wsdl/soap/http" )) { handlerChain.add(payload); }
Gilberto Holms http://gibaholms.wordpress.com/
if (bindingID .equals( "http://java.sun.com/xml/ns/jaxws/2003/05/soap/bind ings/HTTP/" )) { handlerChain.add(payload); } return handlerChain; } }
o 2 – Setar a lista de Handlers na classe Service
Service service = Service .create(wsdlLoc , serviceName ); service.setHandlerResolver(ccResolver );
• Aplicando Handlers no Server
o Anotação @HandlerChain o Seta um arquivo de configuração
@WebService (... ) @HandlerChain (file ="handler-chain.xml" ) public class CreditCardServiceImpl { }