Gwt Request Factory. Generics and Inheritance on client side

六眼飞鱼酱① 提交于 2020-02-23 05:46:48

问题


I am trying to write a generic class to avoid code repetition. I would like to have generic methods for:

  1. Get Entity/Model from server by id.
  2. Get List of all Entities/Models from server.
  3. Send to server and save in db Entity/Model.

It should work with Generic classes, e.g.:

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

I have working server side. Now I struggle with client side code.

The goal is to write:

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

Here is my server side code, which works (doesn't report any compile or run-time errors, as I suppose):

SERVER

GenericModel

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

GenericDao

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
    }

}

GenericLocator

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;
    }
}

CLIENT/SHARED

GenericProxy

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

GenericContext

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

Here is the compilation error that occurs:

[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

As you can see errors point to generated class implementation of mine request factory interfaces. I don't know how to deal with it.

来源:https://stackoverflow.com/questions/33941560/gwt-request-factory-generics-and-inheritance-on-client-side

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!