2014-02-10 76 views
3

我試圖用泛型創建一個單一的服務,而不是創建一百個不同的GWT-RPC服務和serviceAsync類。這裏的接口:在GWT-RPC中使用泛型沒有像預期的那樣工作

@RemoteServiceRelativePath("dispatch") 
public interface CommandService extends RemoteService 
{ 
    public <T> Result<T> execute(Command command, T target); 
} 

這裏Command是一切,我可以發出不同的命令,如Login, Register, ChangePassword的枚舉」等在服務器端,我有Command的關鍵一HashMap,和一個Executor類作爲值。對於每個Command我有一個相應的ExecutorExecutor被執行,並且它的返回值在服務器端返回。

當我嘗試在客戶端上創建CommandServiceAsync並嘗試執行它時,會發生此問題。這裏是我的代碼爲:

public enum Command 
{ 
    LOGIN, 
    REGISTER, 
    CHANGE_PW; 

    public <T> void execute(T target, final ResultReceiver<T> receiver) 
    { 
     CommandServiceAsync command = GWT.create(CommandService.class); 
     command.execute(this, target, new AsyncCallback<Result<T> >() 
     { 
      @Override 
      public void onFailure(Throwable caught) 
      { 
       MyProgram.handleFailure(caught); 
      } 

      @Override 
      public void onSuccess(Result<T> result) 
      { 
       receiver.receive(result);; 
      } 
     }); 
    } 
} 

這裏,Command.execute是實際調用該服務的方法。下面是我如何調用它來執行LOGIN命令:

LoginForm form = new LoginForm(); 
Command.LOGIN.execute(form, new ResultReceiver<LoginForm>() 
{ 
    @Override 
    public void receive(Result<LoginForm> result) 
    { 
     Console.debug("Received result"); 
     //result.getTarget() will return an instance of LoginForm 
     Console.debug("user: " + result.getTarget().getUser()); 
     Console.debug("pw: " + result.getTarget().getUser()); 
    } 
}); 

問題是以下行發生在Command.execute

CommandServiceAsync command = GWT.create(CommandService.class); 

在這裏,我得到以下錯誤:

ERROR: Deferred binding failed for 'com.xxx.CommandService'; expect subsequent failures

ERROR: Uncaught exception escaped com.google.gwt.event.shared.UmbrellaException: Exception caught: Deferred binding failed for 'com.xxx.CommandService' (did you forget to inherit a required module?)

Caused by: com.google.gwt.core.ext.UnableToCompleteException: (see previous log entries)

我該如何完成我想要做的事情?

回答

5

在客戶端GWT應用程序中,編譯時必須知道所有類型。有一個像你所描述的泛型方法是行不通的。

你可以嘗試像下面

public interface CommandService extends RemoteService { 
    public Result<Serializable> execute(Command command, Serializable target); 
} 

你會失去一些類型安全和限制你了一點,但應該工作。

Request Factory可能更適合這種情況。它對服務器端代碼在實際工作中的位置提供了很多寬容。

在GWT源代碼中有一個Request Factory示例項目。 gwtproject.org網站在獲取源代碼here方面有非常明確的說明。查看eclipse目錄中的自述文件。這將幫助你開始。

編輯:

由於@ColinAlworth指出的那樣,你應該在你的RPC方法使用簡單的界面時要非常小心。上面的方法告訴編譯器,它應該能夠通過它可以訪問的線路上的每個Serializable對象發送,並且將爲每一個創建串行器和解串器!

+6

要非常小心這一點 - 你明確告訴它可以發送任何* *序列化對象通過線路的編譯器。 RPC生成器將挑選出GWT可以訪問的任何Serializable,並且將爲它構建序列化器和反序列化器並編譯類型,即使您從未在項目的其他地方使用這些類型。 –

+0

感謝您的支持@ColinAlworth – Jonathan

1

對GWT-RPC使用genrics和Object類是一種不好的方法。有一段時間它會拋出一個序列化異常,有時它不會但不起作用。原因是,GWT在編譯時創建了白名單或序列化策略。爲此,你需要知道你正在使用的確切類。 有關更多細節,請查看以下鏈接

Serialization Exception while making an RPC call

+0

那麼在GWT中使用命令模式的最佳方式是什麼? –

+0

命令模式是推薦用於gwt編程的設計模式之一。如果你觀察,即使是AsyncCallback也是一個例子。但對於gwt -rpc,您不能使用涉及泛型的命令模式。它必須是實現Serializable或IsSeralizable的具體類 –

+0

我明白了。但我不明白命令模式如何用於緩存gwt請求的情況。我看過一個視頻,他在那裏製作了一個Action和'Response'界面。然後他創建了一個以作爲參數的ContactService GWT接口,並返回了一個。但是我不明白爲什麼即使使用'Action'和'Response'也是必要的。它如何被用來實現緩存?有任何想法嗎? –

相關問題