我有一个带有服务和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似乎没用了
有什么想法吗?
答案 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 - 你可能拥有自己的所有持久化实体的基类。
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();
}
}