0

我有一个带有服务和 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);    
}

请求上下文类

@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();

    }
}

应用程序上下文.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 没有 Account findAccount(java.lang.Long) 方法。尝试将 AccountProxy 发送到服务器将导致服务器错误。

我不想在我的域类中添加查找方法。我试图把这个方法放在我的 spring 服务中,但我得到了同样的警告。

使用可以正常工作的定位器进行编辑

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

任何的想法?

4

1 回答 1

2

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

如果您不提供某种类型的查找方法,RequestFactory 将无法在对象到达服务器时对其进行重构——它只能创建全新的对象,这会阻止它与现有数据合并。把它拿走,你还不如重新拥有 RPC。

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

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

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();
  }
}
于 2012-08-19T21:43:08.630 回答