使用Generics和GWT-RPC不能按预期工作

Cli*_*ote 3 java generics gwt gwt-rpc

我试图使用泛型创建单个服务,而不是创建一百个不同的GWT-RPC服务和serviceAsync类.这是界面:

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

这Command是所有我可以发出不同的命令,如枚举Login, Register, ChangePassword"等在服务器端,我有一个HashMap的Command作为重点,以及Executor类作为值.对于每一个Command我都有一个对应的Executor.Executor执行该操作,并在服务器端返回其返回值.

当我尝试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 );;
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

这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() );
    }
});
Run Code Online (Sandbox Code Playgroud)

问题发生在以下行Command.execute:

CommandServiceAsync command = GWT.create(CommandService.class );
Run Code Online (Sandbox Code Playgroud)

在这里,我收到以下错误:

错误:'com.xxx.CommandService'的延迟绑定失败; 期待随后的失败

错误:未捕获的异常转义为com.google.gwt.event.shared.UmbrellaException:捕获异常:'com.xxx.CommandService'的延迟绑定失败(您是否忘记继承所需的模块?)

引起:com.google.gwt.core.ext.UnableToCompleteException :(参见以前的日志条目)

我怎样才能完成我想要做的事情?

Jon*_*han 5

在客户端GWT应用程序中,必须在编译时知道所有类型.拥有像你所描述的那样的通用方法是行不通的.

您可以尝试以下内容

public interface CommandService extends RemoteService {
    public Result<Serializable> execute(Command command, Serializable target);
}
Run Code Online (Sandbox Code Playgroud)

你将失去一些类型安全并限制你一点,但这应该工作.

Request Factory可能更适合这种情况.它提供了很多关于服务器端代码执行实际工作的方面的宽容.

GWT源中有一个Request Factory示例项目.该gwtproject.org网站对获得源代码,非常明确的指示在这里.查看eclipse目录中的README文件.这将有助于您入门.

编辑:

正如@ColinAlworth指出的那样,在RPC方法中使用简单接口时,您应该非常小心.上面的方法告诉编译器它应该能够通过它有权访问的线路发送每个Serializable对象,并为每一个创建序列化器和反序列化器!

  • 要非常小心 - 你明确地告诉编译器它可以通过网络发送*any*serializable对象.RPC生成器将挑选出GWT可以访问的任何Serializable,并为它构建序列化器和反序列化器并编译其类型,即使您从未在项目的其他地方使用这些类型. (6认同)