具有泛型的类型化类的RequestFactory客户端继承

时间:2015-11-27 13:03:37

标签: generics inheritance gwt polymorphism requestfactory

我想知道,是否可以将请求工厂代理/上下文的泛型类用于所有实体的常见操作,例如getById(Long id)

在我的应用程序中,我将有许多类,如类,只有idname参数,所以我想写一次功能,并通过继承类中的继承使用它:

以下是服务器实施:

域模型类

@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 GenericModel(Long id) {
        this();
        this.id = id;
    }
}
   @MappedSuperclass
    public abstract class GenericDictionaryModel<T extends GenericModel<T>> extends GenericModel<T> {

        private String name;
        @Transient
        private String optionDisplayName;
    //  private boolean active = true;

        public String getName() {return name;}
        public void setName(String name) {this.name = name;}
    //  public boolean getActive() {return active;}
    //  public void setActive(boolean stat) {this.active = stat;}
        public String getOptionDisplayName() {return optionDisplayName;}
        public void setOptionDisplayName(String optionDisplayName) {this.optionDisplayName = optionDisplayName;}

        public GenericDictionaryModel() {
            super();
        }
        public GenericDictionaryModel(Long id, String name) {
            super(id);
            this.name = name;
        }

    }
@Entity
public class PageI extends GenericDictionaryModel<PageI> {

    @ManyToMany(cascade = CascadeType.ALL)
    private List<Content> contents;


    /* Getters and Setters */
    public List<Content> getContents() {
        return contents;
    }

    public void setContents(List<Content> contents) {
        this.contents = contents;
    }



}

DAO课程

public class GenericDao<T extends GenericModel<T>> {
    private Logger logger = LoggerFactory.getLogger(this.getClass().getCanonicalName());
    @Transient protected Class<T> entityClass;


    public GenericDao() {
        super();
    }
    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<GenericModel<T>> get() {
        logger.error("trying to get data from db");
        return getList();
    }
//  public List<T> get() {
//  }
    public List<GenericModel<T>> getList() {
        List<T> resultList = JPA.em().createQuery("FROM " + entityClass.getSimpleName()).getResultList();

        logger.error(resultList.toString());
        return JPA.em().createQuery("FROM " + entityClass.getSimpleName()).getResultList();
    }
}
public class GenericDictionaryDao<T extends GenericDictionaryModel<T>> extends GenericDao<T>{
    private Logger logger = LoggerFactory.getLogger(this.getClass().getCanonicalName());

//  public T getBy(Long id) {
//      return super.getBy(id);
//    }
    public List<GenericModel<T>> getByName() {
        return super.get();
    }



//  public List<T> getListOrderedByName() {
//  public List<GenericDictionaryModel> getListOrderedByName() {
    public List<GenericDictionaryModel> getListOrderedByName2() {
        return null;
    }
    public List<GenericDictionaryModel<T>> getListOrderedByName() {
        try {
            return JPA.em()
                      .createQuery("FROM " + entityClass.getSimpleName() + " ORDER BY name")
                      .getResultList();
        } catch (ClassCastException e) {
            return new LinkedList<GenericDictionaryModel<T>>();
        }
//      return null;
    }
}

以下是共享实施:

代理:

@ProxyFor(value = GenericModel.class, locator = GenericLocator.class)
public interface GenericProxy extends EntityProxy {
    public Long getId();
    public void setId(Long id);
    public Integer getVersion();
    public void setVersion(Integer version);
}
@ProxyFor(value = GenericDictionaryModel.class, locator = GenericLocator.class)
public interface GenericDictionaryProxy extends GenericProxy {
    public String getName();
    public void setName(String name);
}
@ProxyFor(value = PageI.class, locator = GenericLocator.class)
public interface PageIProxy extends GenericDictionaryProxy {
    public List<ContentIProxy> getContents();
    public void setContents(List<ContentIProxy> contents);
    public static final String Contents = "contents";
}

上下文/服务:

@Service(value = GenericDao.class, locator = MyServiceLocator.class)
@ExtraTypes( {
    GenericProxy.class 
    } )
public interface GenericContext extends RequestContext {
    Request<GenericProxy> getBy(Long id);
    Request<List<GenericProxy>> get();
    Request<Void> save(GenericProxy entity);
}
@Service(value = GenericDictionaryDao.class, locator = MyServiceLocator.class)
@ExtraTypes( {
    GenericDictionaryProxy.class,
    PageIProxy.class,
    ContentIProxy.class
    } )
public interface GenericDictionaryContext extends GenericContext {
    public Request<List<GenericDictionaryProxy>> getListOrderedByName();
}
public interface Services extends RequestFactory {
    GenericContext getGenericContext();
    GenericDictionaryContext getGenericDictionaryContext();

}

这是客户端执行实现:

    List<GenericDictionaryProxy> proxies = new LinkedList<GenericDictionaryProxy>();
    GenericDictionaryContext context = createRequestFactory().getGenericDictionaryContext();

    context.get().to(new Receiver<List<GenericDictionaryProxy>>() {
        @Override
        public void onSuccess(List<GenericDictionaryProxy> response) {
            for(GenericDictionaryProxy p: response) {
                cont.add(new Label(p.getId() + " " + p.getName() + ", " + p.getVersion() ));
            }
        }
    }).fire();

哪个应该返回一个带参数的对象列表:id,version,name。

不幸的是它起作用了。

我的IDE显示错误:

Could not find domain method similar to java.util.List<pl.derp.server.model.GenericDictionaryModel<T>> getListOrderedByName()   GenericDictionaryContext.java   /Index/src/main/java/pl/derp/shared/rf  line 26 Annotation Problem (Java 6 processor)
The method to(Receiver<? super List<GenericProxy>>) in the type Request<List<GenericProxy>> is not applicable for the arguments (new Receiver<List<GenericDictionaryProxy>>(){})    GoodbyeViewImpl.java    /Index/src/main/java/pl/derp/client/view    line 91 Java Problem

以下是编译错误:

[INFO]    Tracing compile failure path for type 'pl.derp.client.view.GoodbyeViewImpl'
[INFO]       [ERROR] Errors in 'file:/home/korbeldaniel/git/derp3/tutorial/src/main/java/pl/derp/client/view/GoodbyeViewImpl.java'
[INFO]          [ERROR] Line 91: The method to(Receiver<? super List<GenericProxy>>) in the type Request<List<GenericProxy>> is not applicable for the arguments (new Receiver<List<GenericDictionaryProxy>>(){})
[INFO]    [ERROR] Hint: Check the inheritance chain from your module; it may not be inheriting a required module or a module may not be adding its source path entries properly

请告诉我我做错了什么。

1 个答案:

答案 0 :(得分:1)

是的,这对您有用,但您需要在RequestContext上为所需的所有不同类型添加@ExtraTypes注释。

我不久前发布了一个完整的例子。

GWT polymorphic lists with @ExtraTypes

修改

要使其工作,您应该使您的通用请求上下文使用泛型。这是我过去所做的,它对我来说是正确的。你不会需要通用的额外类型来使这项工作,因为你将告诉它类型。

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


@Service(value = GenericDictionaryDao.class, locator = MyServiceLocator.class)
@ExtraTypes( {
    GenericDictionaryProxy.class,
    PageIProxy.class,
    ContentIProxy.class
    } )
public interface GenericDictionaryContext extends GenericContext<GenericDictionaryProxy> {
    public Request<List<GenericDictionaryProxy>> getListOrderedByName();

    // These used to be required due to a bug a while ago. Test without it
    // but if you get a method about an unknown method then this is the issue.
    Request<GenericDictionaryProxy> getBy(Long id);
    Request<List<GenericDictionaryProxy>> get();
    Request<Void> save(T entity);
}

前一段时间我发现了一个问题,不确定它是否已修复但我还必须将这些方法添加到扩展类中。我不介意因为我仍然被允许在需要时使用我的GenericContext并且一切正常。这允许我使用番石榴LoadingCache创建一个很好的实体缓存机制。

简单示例。

public class EntityCache<T extends GenericProxy, R extends GenericContext<T>>  {

    private R requestContext;

    public EntityCache(R requestContext) {
        this.requestContext = requestContext;
    }

    public T get(Long key) {
       // get from loading cache but this is a simple example.
       requestContext.get(key);
    }

}