1

我将 GWT 2.2 与 RequestFactory 一起使用。该应用程序有一个现有的服务层(服务器端),所以我使用 ServiceLocator 来提供这些实现。我的 Proxy 和 RequestContexts 指定要使用的正确服务和定位器(如此处所示)。我能够对数据提出基本请求,但是当我尝试保存时,出现以下异常:

com.google.gwt.requestfactory.server.UnexpectedException: Could not instantiate Locator com.schedgy.core.service.OrganizationService. Is it default-instantiable?
at com.google.gwt.requestfactory.server.ServiceLayerDecorator.die(ServiceLayerDecorator.java:185)
at com.google.gwt.requestfactory.server.LocatorServiceLayer.newInstance(LocatorServiceLayer.java:222)
at com.google.gwt.requestfactory.server.LocatorServiceLayer.createLocator(LocatorServiceLayer.java:47)
at com.google.gwt.requestfactory.server.ServiceLayerDecorator.createLocator(ServiceLayerDecorator.java:54)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

OrganizationService 的定义如下:

// Parent class provides the generic Locator<Organization, String> methods
public class OrganizationService extends CompanyEntityService<Organization> {

        protected OrganizationDao organizationDao;

        protected UserDao userDao;

        protected RoleDao roleDao;

        @Inject
        public OrganizationService(
                OrganizationDao organizationDao,
                UserDao userDao,
                RoleDao roleDao) {

            super(organizationDao, Organization.class);

            this.organizationDao = organizationDao;
            this.userDao = userDao;
            this.roleDao = roleDao;
        }

... additional methods
}

我的定位器类看起来像:

public class CompanyServiceLocator implements ServiceLocator {

    protected Injector injector;

    public CompanyServiceLocator() {        
        injector = GuiceFactory.getInjector();
    }

    @Override
    public Object getInstance(Class<?> clazz) {
        return injector.getInstance(clazz);
    }
}

OrganizationProxy 看起来像:

@ProxyFor(value=Organization.class, locator=OrganizationService.class)
public interface OrganizationProxy extends CompanyEntityProxy {
... setters/getters defined here
}

OrganizationRequest 看起来像:

@Service(value=OrganizationService.class, locator=CompanyServiceLocator.class)
public interface OrganizationRequest extends RequestContext {
...
}

客户端代码如下所示:

OrganizationRequest req = organizationRequestFactory.request();
req.paginate(0, 10).fire(paginationReceiver); // Works!

req = organizationRequestFactory.request();
OrganizationProxy org = req.create(OrganizationProxy.class);
org.setName("test");
req.save(org).fire(receiver); // This causes the server side exception

很明显,ServiceLayerDecorator 无法实例化 OrganizationService,因为它没有默认构造函数,但这就是我使用 Guice 并重写 ServiceLocator 以使用 Guice 创建服务实例的原因。但是为什么第一个调用正确地使用了我的 ServiceLocator 而第二个没有呢?

4

2 回答 2

4

定位器必须是默认可实例化的。

@ProxyFor(value=Organization.class, locator=OrganizationService.class)

是事情出轨的地方。如果要实现接口OrganizationService的销售实例,则需要使其默认可实例化或注入一个实现接口。OrganizationLocatorServiceLayerDecoratorcreateLocator()

第一个代码示例起作用而不是第二个的原因是第二个代码示例正在创建和改变Organization基于来自客户端的命令。在这种情况下Locator.create(),必须由 RequestFactory 服务器代码调用。在不知道paginate()返回给客户端的内容的情况下,我怀疑没有Organization返回任何实例,因为有必要调用Locator.getId()andLocator.getVersion()方法。

于 2011-04-05T14:17:34.607 回答
1

我仍然对为什么两个类需要为定位器提供实现感到困惑,但这是我能够解决这个问题的方法。

扩展默认的 RequestFactoryServlet 以便您可以默认注入您的自定义 ServiceLayerDecorator。

public class CompanyRequestFactoryServlet extends RequestFactoryServlet {

    public CompanyRequestFactoryServlet() {
        this(new DefaultExceptionHandler(), new CompanyServiceLayerDecorator());
    }

    public SchedgyRequestFactoryServlet(ExceptionHandler exceptionHandler,
            ServiceLayerDecorator... serviceDecorators) {
        super(exceptionHandler, serviceDecorators);
    }
}

创建一个 ServiceLayerDecorator 来提供定位器的实例。我使用 Guice,所以这很容易。下面代码中的 GuiceFactory 只是一个提供 Guice Injector 实例的单例。

public class CompanyServiceLayerDecorator extends ServiceLayerDecorator {

    @Override
    public <T extends Locator<?, ?>> T createLocator(Class<T> clazz) {
        return GuiceFactory.getInjector().getInstance(clazz);
    }
}

最后,更新您的 web.xml 以使用您的自定义 servlet:

<servlet>
    <servlet-name>requestFactoryServlet</servlet-name>
    <servlet-class>com.company.core.requestfactory.CompanyRequestFactoryServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>requestFactoryServlet</servlet-name>
    <url-pattern>/gwtRequest</url-pattern>
</servlet-mapping>
于 2011-04-06T15:15:19.340 回答