我正在尝试从CDI 1.0升级到CDI 1.2,但是我面临以下问题:

org.jboss.weld.exceptions.UnserializableDependencyException: WELD-001413: The bean Managed Bean [class ViewProcessContext] with qualifiers [@Default @Named @Any] declares a passivating scope but has a non-passivation-capable dependency Producer Method [ConfigurationReader] with qualifiers [@Default @Any] declared as [[BackedAnnotatedMethod] @Produces @Default @Singleton public ConfigurationReaderProducer.process()]
    at org.jboss.weld.bootstrap.Validator.validateInjectionPointPassivationCapable(Validator.java:442)
    at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:380)
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:277)
    at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:130)
    at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:151)
    at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:494)
    at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:64)
    at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:62)
    at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:62)
    at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:55)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)


以下是在CDI 1.0上正常运行的代码:

错误发生的地方:

@Named
@ConversationScoped
public class ViewProcessContext implements Externalizable {
//...
    @Inject
    private ConfigurationReader compReader;
//...
}


注入依赖项:

public interface ConfigurationReader extends Serializable {
}


制片人:

@ApplicationScoped
public class ConfigurationReaderProducer implements Externalizable {
//...
@Produces
    @Default
    @Singleton
    public ConfigurationReader process() {
    }
}


根据CDI spec


  生产者方法在且仅当从不具有钝化能力
  返回一个在运行时不具有钝化能力的值。


因此,我的生产者总是返回一个具有钝化能力的实例。
我不明白为什么Weld抱怨。

在这种情况下,对生产者或依赖项无效的是什么?

最佳答案

嗯,我可以重提您的问题。我重新阅读了CDI 1.0和1.2规范。实际上,CDI 1.2比CDI 1.0更加清晰,据我所知,Weld中的更改是相当正确的。

http://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#passivating_scope

第一:生产者方法的验证:

6.6.5。可钝化的bean和依赖项的验证


  如果生产者方法声明了钝化范围,并且:
  
  
  具有声明为final且不实现或扩展Serializable的返回类型,或者,
  具有无法钝化的注入点。
  


6.6.1具有钝化能力的bean


  当且仅当生产方方法从不返回在运行时不具有钝化能力的值时,该生产者方法才具有钝化能力。


结论:如果要在具有钝化作用域的结果中使用结果,则必须始终使用具有钝化作用的注释对生产者方法进行注释。

那么,哪些范围可以钝化?答:只有会话和会话范围以及您自己的声明@NormalScope(passivating = true)的范围。意味着@Singleton不是(请参见6.6.4。钝化作用域)。

您也许可以解决该问题,但是:

您是否真的希望在您的sessionScope Bean中使用Singleton?当您对sessionScoped-Bean进行钝化时,您的Singleton也将被钝化。您需要实现readResolve和writeReplace(请参阅Serializable Api)才能真正创建单例。周围将没有代理对象。

重新考虑您的解决方案,在大多数情况下,您需要的是(代理)applicationScoped-Object。

不过,实际上,您可以通过标准@Inject机制将@ Singleton-Bean注入@ConversationScope(没有生产者,只是普通注入)。请注意,@ Singleton-bean不会被bean.xml和bean-discovery-mode =“ annotated”自动检测到(并且您需要如所述的readResolve等)。

最后:您可以简单地注入单例但不能通过生产者方法有意义吗?我会说:不。抱歉,这就是规范中的内容。

祝好运。

09-26 06:40