2015-10-01 22 views
2

我有一個可能或可能返回null的可注入提供程序。當它爲空時我收到一個異常。我註冊提供程序作爲一個單身人士,我可以註冊它作爲一種SingletonContext,我自定義爲supportsNullCreation()返回true?我想如果我可以做到這一點,即使findOrCreate()返回null,我的代碼仍然會運行,這是我想要的。如何在Jersey中使用supportsNullCreation()?

@ApplicationPath("rest") 
public class MyApplication extends ResourceConfig 
{ 
    public MyApplication() 
    { 
     ... 
    // Provider of DB 
    this.register(new AbstractBinder() 
    { 
     @Override 
     public void configure() 
     { 
bindFactory(DbManager.class).to(EntityManagerFactory.class).in(Singleton.class); 
     } 
    }); 
} 

然後這樣使用:

@Singleton 
@Path("myservice") 
public class WebServiceClass 
{ 
    // NOTE: Right now I have to comment this to run without a DB 
    @Inject 
    private EntityManagerFactory entityManagerFactory = null; 
    ... 

我得到的例外是這個...

java.lang.IllegalStateException: Context 
[email protected] findOrCreate returned a null for 
descriptor SystemDescriptor(
    implementation=com.db.DbManager 
    contracts={javax.persistence.EntityManagerFactory} 
    scope=javax.inject.Singleton 
    qualifiers={} 
    descriptorType=PROVIDE_METHOD 
    descriptorVisibility=NORMAL 
    metadata= 
    rank=0 
    [email protected]f2b1 
    proxiable=null 
    proxyForSameScope=null 
    analysisName=null 
    id=145 
    locatorId=0 
    identityHashCode=863132354 
    reified=true) 
    at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2075) 
... 

回答

2

我將建議改變設計了一下。在資源類中使用EntityManagerFactory並不是非常棒的設計。你留下類似代碼

public class Resource { 
    private EntityManagerFctory emf; 

    @POST 
    public Response get(Entity e) { 
     EntityManager em = emf.createEntityManager(); 
     em.getTransaction().begin(); 
     em.persist(e); 
     em.getTransaction().commit(); 
     em.close(); 
    } 
} 

這張照片有很多錯誤。對於你打破[單一責任原則] [1]。其次,這不允許你優雅地處理EMF,即使這是可能的。你有這個全部的地方

if (emf != null) { 
    // do code above 
} else { 
    // do something else. 
} 

此外,它不是偉大的測試。常見模式是使用DAO圖層。就個人而言,我甚至在DAO和REST層之間添加了一個服務層,但是你只需要一個DAO層即可。

例如,我會做的是爲數據訪問調用創建一個公共抽象接口。

public interface DataService { 
    Data getData(); 
} 

然後創建了數據庫訪問

public class WithDbService implements DataService { 
    private EntityManagerFactory emf; 

    public WithDbService(EntityManagerFactory emf) { 
     this.emf = emf; 
    } 

    @Override 
    public Data getData() { 
     ... 
    } 
} 

然後創建一個沒有DB訪問另一實施方案的實施。

public class WithoutDbService implements DataService { 
    @Override 
    public Data getData() {} 
} 

然後你可以使用一個Factory創建DataService。你會做的是使用ServiceLocator來嘗試找到EMF。如果不爲空,則返回WithDbService否則返回WithoutDbService

public class DataServiceFatory implements Factory<DataService> { 

    private DataService dataService; 

    @Inject 
    public DataServiceFactory(ServiceLocator locator) { 
     // abbreviated for brevity 
     EMF emf = locator.getService(EMF.class); 
     if (emf != null) { 
      dataService = new WithDbService(emf); 
     } else { 
      dataService = new WithoutDbService(); 
     } 
    } 

    @Override 
    public DataService provider() { return dataService; } 
} 
[...] 
bindFactory(DataServiceFactory.class).to(DataService.class).in(..); 

然後,你可以注入DataService每一個地方。只要這兩個實施遵循合同,它應該工作得很好。

可能會有一些設計方面的改進,但它直接在資源類中使用EMF是一大步。

+0

非常感謝!這完全解決了問題,並且設計也更好。 – Coder1224

相關問題