Resumo Anotacoes JAX-WS Certificacao SCDJWS 5

11
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;

description

Meus resumos e anotações da época que fiz a prova de certificação java SCDJWS 5 (nova OCPJWS).

Transcript of Resumo Anotacoes JAX-WS Certificacao SCDJWS 5

Page 1: 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;

Page 2: Resumo Anotacoes JAX-WS Certificacao SCDJWS 5

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(

Page 3: Resumo Anotacoes JAX-WS Certificacao SCDJWS 5

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)

Page 4: Resumo Anotacoes JAX-WS Certificacao SCDJWS 5

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

Page 5: Resumo Anotacoes JAX-WS Certificacao SCDJWS 5

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); }

Page 6: Resumo Anotacoes JAX-WS Certificacao SCDJWS 5

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

Page 7: Resumo Anotacoes JAX-WS Certificacao SCDJWS 5

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

Page 8: Resumo Anotacoes JAX-WS Certificacao SCDJWS 5

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);

Page 9: Resumo Anotacoes JAX-WS Certificacao SCDJWS 5

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

Page 10: Resumo Anotacoes JAX-WS Certificacao SCDJWS 5

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); }

Page 11: Resumo Anotacoes JAX-WS Certificacao SCDJWS 5

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 { }