requestfactory抱怨找方法

时间:2012-08-19 21:03:51

标签: spring gwt requestfactory

我有一个带有服务和dao层的spring(3.1)应用程序。 我尝试在这个春天层使用requestfactory(gwt 2.4)。

这是我的一些课程

我的域名

public class Account {
  Long id;
  String username;
  // get, set
}

spring和gwt之间的桥梁

public class SpringServiceLocator implements ServiceLocator {

    @Override
    public Object getInstance(Class<?> clazz) {
        HttpServletRequest request = RequestFactoryServlet.getThreadLocalRequest();
        ServletContext servletContext = request.getSession().getServletContext();
        ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);
        return context.getBean(clazz);
    }
}

我的帐户代理

@ProxyFor(value=Account.class, locator = AccountLocator.class)
public interface AccountProxy extends EntityProxy{
    public Long getId();
    public String getUsername();

    public void setUsername(String userName);
    public void setId(Long id);    
}

RequestContext类

@Service(locator = SpringServiceLocator.class, value =AccountService.class)
public interface AccountRequest extends RequestContext {
    Request<List<AccountProxy>> loadAllAccounts();
}

我的requestFactory类

public interface AccountRequestFactory extends RequestFactory {
    AccountRequest accountRequest();
}

我的春季服务

public interface AccountService {
    public List<Account> loadAllAccounts();
}

@Service
public class AccountServiceImpl implements AccountService{
    @Autowired
    private AccountDAO accountDAO;
}

帐户定位器,以避免将方法放入实体

public class AccountLocator extends Locator<Account, Long> {

    @Autowired
    private AccountDAO accountDAO;

    @Override
    public Account create(Class<? extends Account> clazz) {
       return new Account();

    }
}

的applicationContext.xml

<context:annotation-config />
<context:component-scan base-package="com.calibra" />
<bean id="accountService" class="org.calibra.server.service.AccountServiceImpl"/>
<bean id="accountDAO" class="org.calibra.server.dao.AccountDAOImpl"/>

演示工作,但我收到此错误:

com.google.web.bindery.requestfactory.server.UnexpectedException:找不到包含密钥类型的单个参数的静态方法

同样在我的AccountProxy上我得到了这个抱怨(警告)

域类型org.calibra.domain.Account没有帐户findAccount(java.lang.Long)方法。尝试将AccountProxy发送到服务器将导致服务器错误。

我不想在我的域类中添加find methond。 我试着把这个方法放在我的春季服务中,但我得到同样的警告。

使用可正常运行的定位器进行编辑

奇怪的是我需要将bean放在applicationContext中,context:annotation和context:component-scan似乎没用了

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

  

域类型org.calibra.domain.Account没有帐户findAccount(java.lang.Long)方法。

如果你没有提供某种类型的find方法,RequestFactory无法在到达服务器时重构对象 - 它只能创建全新的对象,这会阻止它与现有数据合并。拿走它,你也可以再次使用RPC。

如果您不想要静态方法,请提供能够查找对象的Locator实例。来自https://developers.google.com/web-toolkit/doc/latest/DevGuideRequestFactory#locators

  

如果您不想在实体本身中实现持久性代码,该怎么办?要实现所需的实体定位器方法,请创建一个扩展定位器的实体定位器类:

public class EmployeeLocator extends Locator<Employee, Long> {
  @Override
  public Employee create(Class<? extends Employee> clazz)
  {
    return new Employee();
  }
  ...
}
  

然后将它与@ProxyFor注释中的实体相关联:

@ProxyFor(value = Employee.class, locator = EmployeeLocator.class)
public interface EmployeeProxy extends EntityProxy {
  ...
}

您需要实现所有方法,而不仅仅是创建 - 而您感兴趣的主要方法是find(Class, Long)。可以对所有代理使用一个Locator类型 - 从2.4.0和2.5.0-rc1开始,可以安全地实现getDomainType(),以及所有其他需要的方法知道确切的类型是作为参数提供的。

以下是JPA和Guice的示例,但我认为这个想法很清楚,可以使用Spring和您正在使用的任何持久性机制来实现。这里,所有实体都应该实现HasVersionAndId,允许定位器概括如何调用getVersion和getId - 你可能拥有自己的所有持久化实体的基类。

(来自https://github.com/niloc132/tvguide-sample-parent/blob/master/tvguide-client/src/main/java/com/acme/gwt/server/InjectingLocator.java

public class InjectingLocator<T extends HasVersionAndId> extends Locator<T, Long> {
  @Inject
  Provider<EntityManager> data;

  @Inject
  Injector injector;

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

  @Override
  public T find(Class<? extends T> clazz, Long id) {
    return data.get().find(clazz, id);
  }

  @Override
  public Class<T> getDomainType() {
    throw new UnsupportedOperationException();//unused
  }

  @Override
  public Long getId(T domainObject) {
    return domainObject.getId();
  }

  @Override
  public Class<Long> getIdType() {
    return Long.class;
  }

  @Override
  public Object getVersion(T domainObject) {
    return domainObject.getVersion();
  }
}