@Inject无法在AttributeConverter中工作

Sve*_*lav 5 jpa glassfish converter cdi

我有一个简单的AttributeConverter实现,我尝试注入一个必须提供转换逻辑的对象,但@Inject似乎不适用于这种情况.转换器类看起来像这样:

@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);
    }
}
Run Code Online (Sandbox Code Playgroud)

@Converter触发它时会抛出一个NullPointerException因为该属性crypto没有从容器初始化.这是为什么?

我正在使用Glassfish 4,在所有其他情况下@Inject工作得很好.

是否无法在转换器上使用CDI?

任何帮助将不胜感激 :)


我的问题的重点是AttributeConverter部分.我知道,要使CDI工作,bean必须满足http://docs.oracle.com/javaee/6/tutorial/doc/gjfzi.html所述的条件.我也尝试通过实现以下构造函数来强制CDI工作:

@Inject
public String2ByteArrayConverter(Crypto crypto) 
{
    this.crypto = crypto;
}
Run Code Online (Sandbox Code Playgroud)

现在我得到以下异常,但没有给我任何线索:

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)
...
Run Code Online (Sandbox Code Playgroud)

我甚至尝试使用@Producer或@Decorator让CDI在那个地方工作,但我仍然认为AttributeConverter有一些特定的东西不允许CDI.所以问题还没有解决.

fai*_*alb 6

遗憾的是,您无法将CDI bean注入JPA转换器,但是在CDI 1.1中,您可以通过编程方式注入加密:

Crypto crypto  = javax.enterprise.inject.spi.CDI.current().select(Crypto.class).get()
Run Code Online (Sandbox Code Playgroud)


Sve*_*lav 0

好吧,CDI仍然不适用于AttributeConverter,这将是最优雅的解决方案,但我找到了一个令人满意的解决方法。解决方法是使用@FacesConverter. 不幸的是,默认情况下,CDI 也无法在面孔转换器验证器中工作,但是感谢Apache MyFaces CODI API,您可以使其在不使用@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;
    }   
}
Run Code Online (Sandbox Code Playgroud)

注入的托管 bean 必须使用@Named某些范围定义进行显式注释。声明faces-config.xml 不起作用!在我的解决方案中,它看起来像这样:

@Named
@SessionScoped
public class PatientController extends PersistanceManager
{
   ...
}
Run Code Online (Sandbox Code Playgroud)

现在转换器中有上下文信息。就我而言,它是会话/用户特定的加密配置。

当然,在这样的解决方案中,很可能@FacesValidator还需要自定义,但由于CODI,人们也可以在这里使用 CDI(模拟转换器)。