GWT 请求工厂 +服务定位器错误
我将 GWT 2.2 与 RequestFactory 一起使用。该应用程序有一个现有的服务层(服务器端),因此我使用 ServiceLocator 来提供这些实现。我的 Proxy 和 RequestContexts 指定要使用的正确服务和定位器(如此处< /a>)。我能够对数据发出基本请求,但是当我尝试保存时,出现以下异常:
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,而第二个调用却不能?
I am using GWT 2.2 with RequestFactory. The app has an existing service layer (server side) so I am using a ServiceLocator to provide these implementations. My Proxy and RequestContexts specify the correct service and locator to use (as shown here). I am able to make basic requests for data but when I try to save, I get the following exception:
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 is defined like:
// 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
}
My locator class looks like:
public class CompanyServiceLocator implements ServiceLocator {
protected Injector injector;
public CompanyServiceLocator() {
injector = GuiceFactory.getInjector();
}
@Override
public Object getInstance(Class<?> clazz) {
return injector.getInstance(clazz);
}
}
The OrganizationProxy looks like:
@ProxyFor(value=Organization.class, locator=OrganizationService.class)
public interface OrganizationProxy extends CompanyEntityProxy {
... setters/getters defined here
}
The OrganizationRequest looks like:
@Service(value=OrganizationService.class, locator=CompanyServiceLocator.class)
public interface OrganizationRequest extends RequestContext {
...
}
The client side code looks something like:
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
It is obvious to me that ServiceLayerDecorator cannot instantiate OrganizationService because it does not have a default constructor, but this is why I am using Guice and have over-written the ServiceLocator to use Guice to create instances of the service. But why does the first call correctly use my ServiceLocator whereas the second does not?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
定位器必须是默认可实例化的。
事情正在偏离轨道。如果
OrganizationService
正在出售Organization
实例来实现Locator
接口,您需要将其设置为默认可实例化或注入>ServiceLayerDecorator
实现createLocator()
。第一个代码示例有效而第二个代码示例无效的原因是,第二个代码示例正在根据客户端的命令创建和更改
Organization
。在这种情况下,Locator.create()
必须由 RequestFactory 服务器代码调用。在不知道paginate()
返回给客户端的情况下,我怀疑没有返回Organization
的实例,因为有必要调用Locator.getId( )
和Locator.getVersion()
方法。Locators must be default-instantiable.
is where things are going off the rails. If the
OrganizationService
is vending instances ofOrganization
to fulfill theLocator
interface, you'll need to make it default-instantiable or inject aServiceLayerDecorator
that implementscreateLocator()
.The reason that the first code sample works and not the second is that the second code sample is creating and mutating an
Organization
based on commands from the client. In this caseLocator.create()
must be called by the RequestFactory server code. Without knowing whatpaginate()
returns to the client, I suspect that no instances ofOrganization
are being returned since it would be necessary to call theLocator.getId()
andLocator.getVersion()
methods.我仍然对为什么两个类需要提供定位器的实现感到困惑,但这是我如何解决这个问题的。
扩展默认的 RequestFactoryServlet,以便您可以默认注入自定义 ServiceLayerDecorator。
创建一个 ServiceLayerDecorator 来提供 Locator 的实例。我使用 Guice,所以这很简单。下面代码中的 GuiceFactory 只是一个提供 Guice Injector 实例的单例。
最后,更新您的 web.xml 以使用您的自定义 servlet:
I am still confused on why two classes need to provide implementations for Locators, but here is how I was able to fix this problem.
Extend the default RequestFactoryServlet so that you can inject your custom ServiceLayerDecorator by default.
Create a ServiceLayerDecorator to provide instances of your Locator's. I use Guice, so this was quite easy. GuiceFactory in the below code is just a singleton that provides an instance of the Guice Injector.
Finally, update your web.xml to use your custom servlet: