Vraptor + WebService

Galera possuo um projeto usando Vraptor, preciso criar agora um webservice e neste webservice utilizar os objetos instanciados pelo vraptor, alguém sabe me dizer se isso é possível e como fazer? Pois usando o processo normal de colocar os objetos no construtor da classe não deu certo.

Obrigado!

Tem como explicar melhor o que você quer?
Esse texto está um pouco confuso…

[]'s
Daniel

Por exemplo Tenho uma classe ClienteDAO, onde utilizou no ClienteControler, na classe ClienteControler passo o ClienteDAO no construtor, e o Vraptor se encarrega de gerar a instancia.

Gostaria de fazer o mesmo no WebService, mas utilizando esta pratica de passar o objeto pelo construtor não dá certo com o WebService, então gostaria de saber se é possível e como passar objetos instanciados pelo vraptor a uma classe Webservice, para que o Webservice utilize estes objetos.

O WebService está no mesmo projeto, gostaria de por exemplo usar o ClienteDAO dentro da classe do Webservice.

como vc está publicando esse webService?

Criei a classe


/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.clog.webservice;

import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebParam;

@WebService(serviceName = "WSTeste")
public class WSTeste {

    /** This is a sample web service operation */
    @WebMethod(operationName = "hello")
    public String hello(@WebParam(name = "name") String txt) {
        return "Hello " + txt + " !";
    }
}

Configurei o web.xml

    <servlet>
        <servlet-name>WSTeste</servlet-name>
        <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
        <load-on-startup>60</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>WSTeste</servlet-name>
        <url-pattern>/WSTeste</url-pattern>
    </servlet-mapping>

Configurei o sun-jaxws.xml

<?xml version="1.0" encoding="UTF-8"?>
<endpoints version="2.0" xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime">
  <endpoint implementation="br.com.clog.webservice.WSTeste" name="WSTeste" url-pattern="/WSTeste"/>  
</endpoints>

Desta forma o projeto roda, pois não estou passando nada no webservice, com citei a cima se precisar utilizar um objeto ClienteDAO, passando pelo construtor como o exemplo abaixo o projeto não sobe no servidor.

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.clog.webservice;

import br.com.caelum.vraptor.Resource;
import br.com.clog.dao.ClienteDAO;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebParam;

@Resource
@WebService(serviceName = "WSTeste")
public class WSTeste {

    private ClienteDAO clienteDAO;

    public WSTeste(ClienteDAO cliente) {
        this.clienteDAO = clienteDAO;
    }

    /** This is a sample web service operation */
    @WebMethod(operationName = "hello")
    public String hello(@WebParam(name = "name") String txt) {
        return "Hello " + txt + " !"+clienteDAO;
    }
}

Erro


27/10/2011 12:34:53 org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class com.sun.xml.ws.transport.http.servlet.WSServletContextListener
com.sun.xml.ws.transport.http.servlet.WSServletException: WSSERVLET11: failed to parse runtime descriptor: [failed to localize] WSSERVLET43: failed to instantiate service implementor for port "class br.com.clog.webservice.WSTeste"()
	at com.sun.xml.ws.transport.http.servlet.WSServletContextListener.contextInitialized(WSServletContextListener.java:139)
	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4681)
	at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5184)
	at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5179)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)
Caused by: com.sun.xml.ws.server.ServerRtException: [failed to localize] WSSERVLET43: failed to instantiate service implementor for port "class br.com.clog.webservice.WSTeste"()
	at com.sun.xml.ws.api.server.InstanceResolver.createNewInstance(InstanceResolver.java:218)
	at com.sun.xml.ws.api.server.InstanceResolver.createDefault(InstanceResolver.java:180)
	at com.sun.xml.ws.server.EndpointFactory.createEndpoint(EndpointFactory.java:123)
	at com.sun.xml.ws.api.server.WSEndpoint.create(WSEndpoint.java:505)
	at com.sun.xml.ws.transport.http.DeploymentDescriptorParser.parseAdapters(DeploymentDescriptorParser.java:253)
	at com.sun.xml.ws.transport.http.DeploymentDescriptorParser.parse(DeploymentDescriptorParser.java:147)
	at com.sun.xml.ws.transport.http.servlet.WSServletContextListener.contextInitialized(WSServletContextListener.java:124)
	... 8 more

então, não adianta colocar @Resource ou @Component, pq não é o VRaptor quem vai criar essa classe, e sim o WSServlet que vc registrou no web.xml…

se não é o VRaptor que cria, ele não consegue injetar dependências por vias normais…

dá pra fazer uma gambi, :wink:

E tem como fazer o Vraptor criar? Se nao vai ter que ser via Gambi mesmo!

não…

um dos jeitos é fazer algo parecido com o que é falado nesse tópico:
http://www.guj.com.br/java/255750-como-trabalhar-com-componentes-e-jobs-no-vraptor-com-taskscheduler-spring#1334391

só que ao invés de invocar por uma task, é invocar de dentro do seu webService (seu WS chamar uma url do servidor)

outro jeito é capturar o Container em alguma classe que tenha um método estático de acesso a ele.

ou ainda usar o spring pra subir o WS (talvez tenha algo assim)

Cara eu já estava adiantando esta parte como teste fiz assim.

WS

package br.com.clog.webservice;

import br.com.clog.model.Cliente;
import java.net.URL;
import java.net.URLConnection;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebParam;

@WebService(serviceName = "WSTeste")
public class WSTeste {

    /** This is a sample web service operation */
    @WebMethod(operationName = "hello")
    public String hello(@WebParam(name = "name") String txt) {
        try {
            URL url = new URL("http://localhost:8084/CLog/ws.cliente_"+txt);
            URLConnection u = url.openConnection();       
            Cliente c=(Cliente) u.getContent();         
            return c.getNome();
        } catch (Exception ex) {
            Logger.getLogger(WSTeste.class.getName()).log(Level.SEVERE, null, ex);
        }
        return "";
    }
}

Desta forma eu chamo o método que está referenciado pelo endereço “/ws.cliente_” passando o código do cliente, este método executa a busca do cliente e retorna o objeto carregado.

Classe gerenciada pelo VRaptor

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.clog.webservice;

import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Resource;
import br.com.clog.model.Cliente;
import br.com.clog.service.ClienteService;

@Resource
public class UtilWS {

    public static ClienteService clienteService;

    public UtilWS(ClienteService clienteService) {
        this.clienteService = clienteService;
    }

    @Path("/ws.cliente_{Cliente.id}")
    public Cliente inicializa(Cliente cliente) {
        cliente = clienteService.obter(cliente);
        return cliente;
    }
}

Mas nao sei porque diabos estou tendo problema ao pegar o objeto devolta da erro de cast, o que é estranho pois o objeto Cliente é serializado, e o cast deveria ocorrer normalmente.

 Cliente c=(Cliente) u.getContent();         

Erro

java.lang.ClassCastException: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream cannot be cast to br.com.clog.model.Cliente at br.com.clog.webservice.WSTeste.hello(WSTeste.java:21) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.sun.xml.ws.api.server.InstanceResolver$1.invoke(InstanceResolver.java:246) at com.sun.xml.ws.server.InvokerTube$2.invoke(InvokerTube.java:146) at com.sun.xml.ws.server.sei.EndpointMethodHandler.invoke(EndpointMethodHandler.java:257) at com.sun.xml.ws.server.sei.SEIInvokerTube.processRequest(SEIInvokerTube.java:95) at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:629) at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:588) at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:573) at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:470) at com.sun.xml.ws.server.WSEndpointImpl$2.process(WSEndpointImpl.java:295) at com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:515) at com.sun.xml.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:285) at com.sun.xml.ws.transport.http.servlet.ServletAdapter.handle(ServletAdapter.java:143) at com.sun.xml.ws.transport.http.servlet.WSServletDelegate.doGet(WSServletDelegate.java:155) at com.sun.xml.ws.transport.http.servlet.WSServletDelegate.doPost(WSServletDelegate.java:189) at com.sun.xml.ws.transport.http.servlet.WSServlet.doPost(WSServlet.java:76) at javax.servlet.http.HttpServlet.service(HttpServlet.java:641) at javax.servlet.http.HttpServlet.service(HttpServlet.java:722) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at br.com.caelum.vraptor.resource.DefaultResourceNotFoundHandler.couldntFind(DefaultResourceNotFoundHandler.java:41) at br.com.clog.resolver.Error404.couldntFind(Error404.java:33) at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:69) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65) at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:70) at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:92) at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:56) at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:89) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at br.com.clog.outros.DisableUrlSessionFilter.doFilter(DisableUrlSessionFilter.java:59) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:498) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:394) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:619)

cuidado, você não está invocando o método diretamente, você está fazendo uma requisição! o getContent te dá a resposta, e não o objeto.

[quote=Lucas Cavalcanti]cuidado, você não está invocando o método diretamente, você está fazendo uma requisição! o getContent te dá a resposta, e não o objeto.
[/quote]

Vixi agora me pegou, sabe me dizer qual seria a forma correta de se invocar este método e obter o objeto de retorno?

Você realmente precisa de um webservice SOAP ou você pode usar rest e retornar XML/JSON pelo controller do vraptor?

jeito fácil de fazer:

http://groups.google.com/group/caelum-vraptor/browse_thread/thread/5ce54b5c5437a884?pli=1

classe Gambiarra

vc pode ao invés de colocar no ServletContext, vc guardar na classe, e ter um método estático que pega a instância que vc precisa (container.instanceFor(classe))

Cara precisa pois o cliente é um sistema no celular usando ksoap, e ele já utiliza conexão via soap.