2015-07-21 51 views
3

我有一個簡單的AttributeConverter實現,其中我嘗試注入一個必須提供轉換邏輯的對象,但@Inject似乎不適用於這種情況。該轉換器類看起來是這樣的:@Inject在AttributeConverter中不工作

@Converter(autoApply=false) 
public class String2ByteArrayConverter implements AttributeConverter<String, byte[]> 
{ 
    @Inject 
    private Crypto crypto; 

    @Override 
    public byte[] convertToDatabaseColumn(String usrReadable) 
    { 
     return crypto.pg_encrypt(usrReadable); 
    } 

    @Override 
    public String convertToEntityAttribute(byte[] dbType) 
    { 
     return crypto.pg_decrypt(dbType); 
    } 
} 

@Converter被觸發,引發NullPointerException因爲屬性crypto不被從容器初始化。這是爲什麼?

我使用的是Glassfish 4,在所有其他情況下@Inject的作品都很好。

在轉換器上不能使用CDI嗎?

任何幫助將不勝感激:)


我的問題的口音更是對AttributeConverter部分。我明白,要讓CDI工作,豆必須符合這裏描述的條件http://docs.oracle.com/javaee/6/tutorial/doc/gjfzi.html。 我還試圖迫使CDI通過實施下面的構造工作:

@Inject 
public String2ByteArrayConverter(Crypto crypto) 
{ 
    this.crypto = crypto; 
} 

現在我得到了以下異常不給我任何線索:

2015-07-23T01:03:24.835+0200|Severe: Exception during life cycle processing 
org.glassfish.deployment.common.DeploymentException: Exception [EclipseLink-28019] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.EntityManagerSetupException 
Exception Description: Deployment of PersistenceUnit [PU_VMA] failed. Close all factories for this PersistenceUnit. 
Internal Exception: Exception [EclipseLink-7172] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.ValidationException 
Exception Description: Error encountered when instantiating the class [class model.converter.String2ByteArrayConverter]. 
Internal Exception: java.lang.InstantiationException: model.converter.String2ByteArrayConverter 
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.createDeployFailedPersistenceException(EntityManagerSetupImpl.java:820) 
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:760) 
... 

我甚至嘗試使用@Producer或@Decorator爲了讓CDI在那個地方工作,但我仍然認爲AttributeConverter有一些特定的東西,它不允許CDI。所以問題還沒有解決。

+0

也許是以下的副本:http://stackoverflow.com/questions/12080317/inject-only-working-for-pojos-created-by-cdi-container – MWiesner

+0

部分它是重複的,但是有一個特定的Spring提供的解決方案不適用於我,因爲我沒有使用Spring。我用一些新的經驗擴展了我的案例的描述,但問題仍未解決。 – Svetoslav

回答

0

好,CDI仍然不爲AttributeConverter工作,這將是最優雅的解決方案,但我找到了令人滿意的解決方法。解決方法是使用@FacesConverter。每默認不幸的是CDI不工作面臨轉換器驗證下去,但多虧了Apache MyFaces CODI API你可以把它的工作unsing的@Advaced註釋:)所以我想出了這樣一個實現:

@Advanced 
@FacesConverter("cryptoConverter") 
public class CryptoJSFConverter implements Converter 
{ 
    private CryptoController crypto = new CryptoController(); 

    @Inject 
    PatientController ptCtrl; 

    public Object getAsObject(FacesContext fc, UIComponent uic, String value) 
    { 
     if(value != null) 
      return crypto.pg_encrypt(value, ptCtrl.getSecretKey()); 
     else 
      return null; 
    } 


    public String getAsString(FacesContext fc, UIComponent uic, Object object) 
    { 
     String res = crypto.pg_decrypt((byte[]) object, ptCtrl.getSecretKey()); 
     return res; 
    } 
} 

注入的託管bean必須用@Named和某個作用域定義進行明確註釋。 faces-config.xml中的聲明不工作!在我的解決方案,它看起來是這樣的:

@Named 
@SessionScoped 
public class PatientController extends PersistanceManager 
{ 
    ... 
} 

現在,一個已在轉換器中的上下文信息。在我的情況下,它是會話/用戶特定的密碼配置。

當然,在這樣的解決方案。它很可能還需要一個定製@FacesValidator,但由於CODI一個對這裏使用CDI也(模擬轉換器)的可能性。

4

可惜你不能注入CDI豆成一個JPA轉換器,但是在CDI 1.1可以通過編程方式注入你的加密:

Crypto crypto = javax.enterprise.inject.spi.CDI.current().select(Crypto.class).get() 
1

您試圖結合兩個不同的世界,因爲CDI不知道JPA Stuff,反之亦然。 (當然一個註釋分析器不知道其他) 你可以做什麼,是這樣的:

/** 
* @author Jakob Galbavy <code>[email protected]</code> 
*/ 
@Converter 
@Singleton 
@Startup 
public class UserConverter implements AttributeConverter<User, Long> { 
    @Inject 
    private UserRepository userRepository; 
    private static UserRepository staticUserRepository; 

    @PostConstruct 
    public void init() { 
     staticUserRepository = this.userRepository; 
    } 

    @Override 
    public Long convertToDatabaseColumn(User attribute) { 
     if (null == attribute) { 
      return null; 
     } 
     return attribute.getId(); 
    } 

    @Override 
    public User convertToEntityAttribute(Long dbData) { 
     if (null == dbData) { 
      return null; 
     } 
     return staticUserRepository.findById(dbData); 
    } 
} 

這樣一來,你可以創建一個Singleton EJB,即在容器的啓動創建,設置PostConstruct階段中的靜態類屬性。然後,您只需使用靜態Repository而不是注入字段(當用作JPA Converter時,它仍然是NULL)。

1

僅供參考,JPA 2.2將允許CDI與AttributeConverter一起使用,並且一些供應商已經支持這個(EclipseLink,DataNucleus JPA是我所知道的那樣做的)。