2015-11-27 95 views
1

我想知道,是否有可能使用泛型類的請求工廠代理/上下文來處理所有實體的常見操作,如getById(Long id)RequestFactory用泛型類型化類的客戶端繼承

在我的應用程序,我將有很多的字典類相似,那將只有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,版本,名稱。

不幸的是它dosent工作。

我的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

是的,這會適用於您,但您需要在您的RequestContext上爲所有您需要的不同類型註冊@ExtraTypes註釋。

我之前發佈了一個完整的示例。

GWT polymorphic lists with @ExtraTypes

編輯

爲了得到這個工作,你應該讓你的普通的RequestContext使用泛型。這是我過去所做的,它對我來說正確運作。你不需要泛型上的額外類型來完成這項工作,因爲你會告訴它的類型。

@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並且一切正常。這讓我創建了一個帶有guava 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); 
    } 

} 
+0

嘿。我已經添加了'@ ExtraTypes'註釋,就像你告訴我的,但不幸的是它沒有幫助。請檢查我的帖子,我已經更新了。 – masterdany88

+0

緩存類非常有趣。你可以發佈客戶端的代碼嗎?你如何創建工廠並調用泛型方法?你能發佈上下文類的代碼嗎?我可以編譯它。 – masterdany88