Фабрика запросов Gwt. Дженерики и наследование на стороне клиента

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

  1. Получить объект/модель с сервера по идентификатору.
  2. Получить список всех сущностей/моделей с сервера.
  3. Отправить на сервер и сохранить в db Entity/Model.

Он должен работать с классами Generic, например:

Services<PizzaProxy> factory = GWT.create(Services.class);
factory.initialize(new SimpleEventBus());
GenericContext<PizzaProxy> context = factory.genericContext();
context.get().to(new Receiver<List<GenericProxy<PizzaProxy>>>() {
    @Override
    public void onSuccess(List<GenericProxy<PizzaProxy>> response) {
        for(GenericProxy<PizzaProxy> p: response) {
            logger.severe(p.getId()) + " " + p.getVersion());
        }
    }
}).fire();

У меня рабочая серверная часть. Теперь я борюсь с кодом на стороне клиента.

Цель состоит в том, чтобы написать:

  • GenericModel,
  • GenericDao,
  • GenericLocator,
  • GenericService,
  • GenericProxy,
  • GenericContext.

Вот мой код на стороне сервера, который работает (как я полагаю, не сообщает об ошибках компиляции или времени выполнения):

СЕРВЕР

ОбщаяМодель

@MappedSuperclass
public  class GenericModel<T extends GenericModel<T>> implements Identifiable, Versionable {
    @Transient
    protected Class<T> entityClass;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Version
    private Integer version;

    // setter & getter
    @Override
    public Long getId() {return id;}
    public void setId(Long id) {this.id = id;}
    @Override
    public Integer getVersion() {return version;}
    public void setVersion(Integer version) {this.version = version;}

    // constructor
    public GenericModel() {
        Class<?> obtainedClass = getClass();
        Type genericSuperclass = null;
        for (;;) {
            genericSuperclass = obtainedClass.getGenericSuperclass();
            if (genericSuperclass instanceof ParameterizedType) {
                break;
            }
            obtainedClass = obtainedClass.getSuperclass();
        }
        ParameterizedType genericSuperclass_ = (ParameterizedType) genericSuperclass;
        try {
            entityClass = ((Class) ((Class) genericSuperclass_
                    .getActualTypeArguments()[0]));
        } catch (ClassCastException e) {
            entityClass = guessEntityClassFromTypeParametersClassTypedArgument();
        }
        }
}

ОбщийДао

public class GenericDao<T extends GenericModel<T>> {
    @Transient protected Class<T> entityClass;

    public GenericDao(Class<? extends GenericModel<T>> clazz) {
        this.entityClass = (Class<T>) clazz;
    }

    public T getBy(Long id) {
        return JPA.em().find(entityClass, id);
    }
    public List<T> get() {
        return getList();
    }
    public List<T> getList() {
        return (List<T>) JPA.em().createQuery("FROM " + entityClass.getSimpleName()).getResultList();
    }


    public void save(T entityClass) {
        JPA.em().persist(entityClass);
    }
    public T saveAndReturn(T entityClass) {
        this.save(entityClass);
        return entityClass;
    }

    public void saveOrUpdate(T entityClass) {
        // TODO
    }

    public void update(T genericDao) {
        JPA.em().merge(genericDao);
    }

    public void delete(T genericDao) {
        JPA.em().remove(genericDao);
    }


    @PrePersist
    protected void prePersist() {
        preUpdate();
    }
    @PreUpdate
    protected void preUpdate() {
        // TODO Update Version
    }

}

Универсальный локатор

public class GenericLocator<GL extends GenericLocator<GL, GD, GM, id>, GD extends GenericDao<GM>, GM extends GenericModel<GM>, id> extends Locator<GenericModel<GM>, Long> {

    @Override
    public GenericModel<GM> create(Class<? extends GenericModel<GM>> clazz) {
        try {
            return clazz.newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public GenericModel<GM> find(Class<? extends GenericModel<GM>> clazz, Long id) {
        GenericDao<GM> dao = new GenericDao<GM>(clazz);
        return dao.getBy(id);
    }


    @Override
    public Class<GenericModel<GM>> getDomainType() {
        GenericModel<GM> model = new GenericModel<GM>();
        return (Class<GenericModel<GM>>) model.getClass();
    }
    @Override
    public Long getId(GenericModel<GM> model) {
        return model.getId();
    }
    @Override
    public Integer getVersion(GenericModel<GM> model) {
        return model.getVersion();
    }
    @Override
    public Class<Long> getIdType() {
        return Long.class;
    }
}

КЛИЕНТ/ОБЩИЙ

Общий прокси

@ProxyFor(value = GenericModel.class, locator = GenericLocator.class)
public interface GenericProxy<T extends GenericProxy<T>> extends EntityProxy {
    public Long getId();
    public Integer getVersion();
}

Общий контекст

@Service(value = GenericDao.class, locator = MyServiceLocator.class)
public interface GenericContext<T extends GenericProxy<T>> extends RequestContext {
    Request<T> getBy(Long id);
    Request<List<T>> get();
    Request<Void> save(T entity);
}

Вот ошибка компиляции, которая возникает:

[INFO]    Adding '2' new generated units
[INFO]       See snapshot: /tmp/pl.derp.shared.rf.GenericContextImpl5428453302732754803.java
[INFO]       Ignored 1 unit with compilation errors in first pass.
[INFO] Compile with -strict or with -logLevel set to TRACE or DEBUG to see all errors.
[INFO]    Tracing compile failure path for type 'pl.derp.shared.rf.GenericContextImpl'
[INFO]       [ERROR] Errors in '/home/korbeldaniel/git/derp3/tutorial/target/.generated/pl/derp/shared/rf/GenericContextImpl.java'
[INFO]          [ERROR] Line 22: T cannot be resolved to a type
[INFO]          [ERROR] Line 29: T cannot be resolved to a type
[INFO]          [ERROR] Line 18: The interface Request cannot be implemented more than once with different arguments: Request<List<T>> and Request<List<T>>
[INFO]          [ERROR] Line 22: T cannot be resolved to a variable
[INFO]          [ERROR] Line 22: Syntax error on token "extends", instanceof expected
[INFO]          [ERROR] Line 30: The interface Request cannot be implemented more than once with different arguments: Request<T> and Request<T>
[INFO]          [ERROR] Line 41: T cannot be resolved to a type
[INFO]          [ERROR] Line 17: T cannot be resolved to a type
[INFO]          [ERROR] Line 30: T cannot be resolved to a type
[INFO]          [ERROR] Line 22: Syntax error on token "class", invalid Name
[INFO]          [ERROR] Line 20: The method with(String...) from the type AbstractRequest<BaseProxy,List<T>> refers to the missing type T
[INFO]          [ERROR] Line 3: The type GenericContextImpl must implement the inherited abstract method GenericContext.save(GenericProxy)
[INFO]          [ERROR] Line 32: The method with(String...) from the type AbstractRequest<BaseProxy,T> refers to the missing type T
[INFO]          [ERROR] Line 18: T cannot be resolved to a type
[INFO]    [ERROR] Hint: Check that the type name 'pl.derp.shared.rf.GenericContextImpl' is really what you meant
[INFO]    [ERROR] Hint: Check that your classpath includes all required source roots
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE

Как видите, ошибки указывают на сгенерированную реализацию класса интерфейсов фабрики запросов. Я не знаю, как с этим справиться.


person masterdany88    schedule 26.11.2015    source источник
comment
Неясно. Что работает ? Что не так? Или вы ищете обзор кода. ПОЖАЛУЙСТА, отредактируйте вопрос или опубликуйте его на codereview.stackexchange.com   -  person kebs    schedule 26.11.2015