有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java GWT RequestFactory+ServiceLocator错误

我在RequestFactory中使用GWT2.2。该应用程序有一个现有的服务层(服务器端),所以我使用ServiceLocator来提供这些实现。My Proxy和RequestContext指定要使用的正确服务和定位器(如图here)。我可以对数据进行基本请求,但当我尝试保存时,会出现以下异常:

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,而第二个调用没有


共 (2) 个答案

  1. # 1 楼答案

    我仍然不明白为什么两个类需要为定位器提供实现,但下面是我如何解决这个问题的

    扩展默认的RequestFactoryServlet,以便可以在默认情况下插入自定义ServiceLayerCorator

    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注入器实例的单例

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

    最后,更新你的网站。使用自定义servlet的xml:

    <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>
    
  2. # 2 楼答案

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

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

    这就是事情偏离轨道的地方。如果OrganizationService正在出售Organization的实例以实现Locator接口,则需要将其设置为默认的instantiable,或者注入一个实现createLocator()ServiceLayerDecorator

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