2009-09-17 10 views
5

Tengo un servicio web con estado desplegado en Tomcat. Consiste en el servicio de fábrica y el servicio API principal, y funciona bien. El servicio de fábrica devuelve un W3CEndpointReference a la instancia de API principal, y el cliente usa la sesión.JAX-WS: WS con estado falla en un proceso independiente

Ahora, intento ejecutar el mismo servicio que una aplicación independiente. En este caso, el W3CEndpointReference devuelto por la fábrica de repente comienza a apuntar al URI de fábrica, no al servicio principal.

Cuando se comparan las referencias de ejecuciones contra Tomcat e independiente, queda claro que la referencia independiente tiene un URI incorrecto. Específicamente, apunta a URI de fábrica, no a API principal.

Aquí es correcta referencia:

... 
<ns3:Address>http://localhost:8080/td2ws/api</ns3:Address> 
... 

Aquí está referencias cuando la fábrica se llama el proceso autónomo:

<Address>http://localhost:9009/td2ws/factory</Address> 

Mi entendimiento de que algo de código bajo el contexto de servlet tiene un conocimiento de la correspondencia entre la clase de servicio (Td2Ws) y es URI, y ajusta las referencias en consecuencia. Sin embargo, esa pieza de código no tiene efecto en el proceso independiente. Incluso puedo sospechar que el código usa sun-jaxws.xml, pero no sé cómo "activarlo".

¿Cómo puedo hacer un servicio web con estado en el trabajo de la aplicación independiente?

Estas son las partes pertinentes del código:

servicio de fábrica (sin estado):

@WebService(targetNamespace="http://server.td2ws.sf.net/") 
public class Td2WsFactory { 
    @WebMethod(operationName="StartSession", action="urn:StartSession") 
    @WebResult(name="Reference") 
    public W3CEndpointReference startSession() { 
     StatefulWebServiceManager<Td2Ws> manager = Td2Ws.getManager(); 

     // for standalone execution only 
     if(manager == null) { 
      manager = new StatefulInstanceResolver<Td2Ws>(Td2Ws.class); 
      Td2Ws.setManager(manager); 
     } 

     Td2Ws session = new Td2Ws(); 
     return manager.export(W3CEndpointReference.class,session); 
    } 
} 

API pleno estado:

@Stateful 
@WebService(targetNamespace="http://server.td2ws.sf.net/") 
@Addressing 
public class Td2Ws { 
    private static StatefulWebServiceManager<Td2Ws> manager; 

    public static void setManager(StatefulWebServiceManager<Td2Ws> manager) { 
     Td2Ws.manager = manager; 
    } 

    public static StatefulWebServiceManager<Td2Ws> getManager() { 
     return Td2Ws.manager; 
    } 

    @WebMethod(operationName="Login", action="urn:Login") 
    public void login(
      @WebParam(name="Username") String username, 
      @WebParam(name="Password") String password, 
      @WebParam(name="Domain") String domain, 
      @WebParam(name="Project") String project 
      ) throws Td2WsException { 

El código de cliente (dirigido a independiente):

public static void main(String[] args) throws Exception { 
    Endpoint epf = Endpoint.publish("http://localhost:9009/td2ws/factory", new net.sf.td2ws.server.Td2WsFactory()); 
    Endpoint eps = Endpoint.publish("http://localhost:9009/td2ws/api", new net.sf.td2ws.server.Td2Ws()); 

    URL factoryUrl = new URL("http://localhost:9009/td2ws/factory?wsdl"); 
    QName factoryQname = new QName("http://server.td2ws.sf.net/", "Td2WsFactoryService"); 

    URL sessionUrl = new URL("http://localhost:9009/td2ws/api?wsdl"); 
    QName sessionQname = new QName("http://server.td2ws.sf.net/", "Td2WsService"); 

    Td2WsFactory factory = new Td2WsFactoryService(factoryUrl,factoryQname).getTd2WsFactoryPort(); 
    System.out.println("factory: "+factory); 

    W3CEndpointReference session = factory.startSession(); 
    System.out.println("session: "+session); 

    Td2WsService service = new Td2WsService(sessionUrl,sessionQname); 
    System.out.println("service: "+service); 

    Td2Ws port = service.getPort(session,Td2Ws.class); 
    System.out.println("port: "+port); 

    port.login(
      Config.get("td.user"), 
      Config.get("td.pass"), 
      Config.get("td.domain"), 
      Config.get("td.project")); 
    System.out.println("logged in..."); 

Ese código falla al iniciar la sesión() como el objeto de destino no tiene ninguna operación de inicio de sesión (que está dirigido erróneamente a la fábrica URI, después de todo):

Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: 
Cannot find dispatch method for {http://server.td2ws.sf.net/}Login 

Respuesta

0

no he hecho esto en un tiempo, pero me dio un vistazo en un servicio web funcional con estado que construí hace algún tiempo. Mis anotaciones son muy similares a la suya, excepto que tengo esta en la parte superior de mi clase:

public class MyService { 

    @Resource 
    WebServiceContext wsCtx; 

    ... 

} 

Aviso no hay modificador, si todo lo demás creo que tiene que ser público, pero no soy positivo. Cómo sabe el contenedor para establecer esto me supera, pero funciona. Solo debe buscar cualquier @Resource de tipo WebServiceContext y configurarlo. Puede acceder a la información de la sesión de esta manera:

HttpServletRequest hRequest = (HttpServletRequest)ctx.getMessageContext().get(MessageContext.SERVLET_REQUEST); 

Session s = hRequest.getSession(); 
+0

El servicio en cuestión es independiente, es decir, no se ejecuta dentro de un contenedor Servlet. –

Cuestiones relacionadas