5

Tomcat にデプロイされたステートフル Web サービスがあります。ファクトリ サービスとメイン API サービスで構成され、問題なく動作します。Factory サービスは W3CEndpointReference をメイン API インスタンスに返し、クライアントはセッションを使用します。

今、私はまったく同じサービスをスタンドアロン アプリケーションとして実行しようとしています。この場合、ファクトリから返された W3CEndpointReference は、メイン サービスの URI ではなく、突然ファクトリ URI を指し始めます。

Tomcat とスタンドアロンに対する実行からの参照を比較すると、スタンドアロン参照の URI が間違っていることが明らかになります。具体的には、メイン API ではなく、ファクトリ URI を指します。

正しい参照は次のとおりです。

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

factory がスタンドアロン プロセスで呼び出される場合の参照は次のとおりです。

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

サーブレット コンテキストの一部のコードは、サービス クラス (Td2Ws) とその URI の間の対応についての知識を持ち、それに応じて参照を調整するという私の理解です。ただし、そのコードはスタンドアロン プロセスでは有効ではありません。コードで sun-jaxws.xml が使用されているのではないかと疑うことさえできますが、「有効にする」方法がわかりません。

スタンドアロン アプリケーションでステートフル Web サービスを機能させるにはどうすればよいですか?

コードの関連部分は次のとおりです。

ファクトリ サービス (ステートレス):

@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:

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

クライアント コード (スタンドアロンを対象):

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

ターゲット オブジェクトにログイン操作がないため、このコードは login() で失敗します (結局、誤ってファクトリ URI にターゲット設定されています)。

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

1 に答える 1

0

しばらくはこれを行っていませんが、しばらく前に構築した機能的なステートフルWebサービスを調べました。私のアノテーションは、クラスのトップにあることを除けば、あなたのアノテーションと非常によく似ています。

public class MyService {

  @Resource
  WebServiceContext wsCtx;

  ...

}

変更者がいないことに注意してください。他に公開する必要があると思いますが、私は前向きではありません。コンテナがこれを設定することをどのように知っているかは私を打ち負かしますが、それは機能します。WebServiceContextタイプの@Resourceを探して、それを設定する必要があります。次のようにセッション情報にアクセスできます。

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

Session s = hRequest.getSession();
于 2013-01-07T21:10:27.917 に答える