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?
Locators must be default-instantiable.
is where things are going off the rails. If the
OrganizationServiceis vending instances ofOrganizationto fulfill theLocatorinterface, you’ll need to make it default-instantiable or inject aServiceLayerDecoratorthat implementscreateLocator().The reason that the first code sample works and not the second is that the second code sample is creating and mutating an
Organizationbased 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 ofOrganizationare being returned since it would be necessary to call theLocator.getId()andLocator.getVersion()methods.