requestfactory жалуется на метод поиска

У меня есть приложение spring (3.1) с сервисом и уровнем dao. Я пытаюсь использовать requestfactory (gwt 2.4) с этим весенним слоем.

Вот некоторые из моего класса

Мой класс домена

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

Мост между пружиной и 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.clera.domain.Account не имеет метода FindAccount(java.lang.Long) учетной записи. Попытка отправить AccountProxy на сервер приведет к ошибке сервера.

Я не хочу добавлять метод поиска в свой класс домена. Я попытался поместить этот метод в свой весенний сервис, но получаю то же предупреждение.

Редактировать с помощью локатора, который работает нормально

Просто странно, мне нужно поместить bean-компонент в applicationContext, context:annotation и context:component-scan кажутся бесполезными

Любая идея?


person robert trudel    schedule 19.08.2012    source источник


Ответы (1)


Для типа домена org.clera.domain.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();
  }
}
person Colin Alworth    schedule 19.08.2012
comment
спасибо за всю эту информацию. После прочтения есть пара вещей, которые я не понимаю. Я не уверен, что полностью понимаю, куда поместить мой весенний сервис, весенний дао, метод, необходимый для локатора. Я предполагаю, что мне нужно создать локатор с определенным методом create и так далее... Я просто использую spring jdbc... поэтому у меня нет entityManager. Я не уверен, но этому классу понадобится Spring dao (конечно, такой же dao, чем моя служба spring...) для метода find. Моя служба spring будет иметь dao spring. My AccountRequest будет продолжать использовать службу spring. Мой прокси-сервер будет использовать мой локатор. - person robert trudel; 20.08.2012
comment
EntityManager - это более или менее конкретный DAO, поэтому просто замените там свой дао - что-то, что может находить/создавать экземпляры. Как только вы объявите Locator, вам останется только сослаться на него из вашей аннотации @ProxyFor и позволить RF создать его. Вы можете повлиять на это создание, создав подкласс RemoteServiceServlet и передав пользовательский экземпляр ServiceLayerDecorator в конструкторе. Затем вам решать, как связать локатор или SLD со Spring, чтобы получить ссылки на компонент DAO. - person Colin Alworth; 20.08.2012
comment
спасибо, что работа я разместил изменение. Полезно ли размещать findAccount в сервисе? Единственное скучно, это весна, я не понимаю, мне нужно поместить бин в applicationContext. Я подумал, что контекст: annotation-config и contex:component-scan избегают помещать настройку bean-компонента в файл xml. - person robert trudel; 21.08.2012