【问题标题】:requestfactory complain about find methodrequestfactory 抱怨 find 方法
【发布时间】:2012-08-21 04:34:10
【问题描述】:

我有一个带有服务和 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 没有 Account findAccount(java.lang.Long) 方法。尝试向服务器发送 AccountProxy 会导致服务器错误。

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

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

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

有什么想法吗?

【问题讨论】:

    标签: spring gwt requestfactory


    【解决方案1】:

    域类型 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();
      }
    }
    

    【讨论】:

    • 感谢您提供所有这些信息。阅读后,有几件事我不明白。我不确定将我的spring服务,spring dao,定位器所需的方法放在哪里。我想我需要使用特定方法创建定位器等等......我只使用spring jdbc......所以我没有entityManager 我不确定,但是这个类将需要一个spring dao(当然相同dao 比我的 spring 服务...) 对于 find 方法我的 spring 服务将有一个 spring dao 我的 AccountRequest 将继续使用 spring 服务我的代理将使用我的定位器
    • EntityManager 或多或少是一个特定的 DAO,所以只需在其中替换您的 dao - 可以找到/创建实例的东西。一旦您声明了 Locator,只需从您的 @ProxyFor 注释中引用它,然后让 RF 创建它。您可以通过继承 RemoteServiceServlet 并在构造函数中传递自定义 ServiceLayerDecorator 实例来影响此创建。然后由您决定如何将定位器或 SLD 绑定到 Spring 以获取对 DAO bean 的引用。
    • 谢谢,我发布了更改。将 findAccount 放在服务中有用吗?唯一无聊的是春天,我不明白我需要把bean放在applicationContext中。我认为 context:annotation-config 和 contex:component-scan 避免将 bean 设置放在 xml 文件中。
    猜你喜欢
    • 2023-02-10
    • 2022-07-06
    • 2014-08-14
    • 2014-11-25
    • 2011-08-05
    • 2019-01-26
    • 1970-01-01
    • 2011-11-29
    • 2012-08-12
    相关资源
    最近更新 更多