覆盖内置主Bean

时间:2013-03-05 21:43:26

标签: java-ee-6 cdi

在Java EE 6中,有一个内置bean类型javax.security.Principal,可以像@Inject Principal principal;那样进行注入。

这是默认情况下,我想知道是否有办法改变它,比如,通过提供生产者方法。

目前,编写生产者方法将导致部署异常。

示例制作者:

my.package;

import javax.security.Principal;

public class MyProducer {

    ...

    @Produces
    public Principal obtainPrincipal() {
        return getMyPrincipal();
    }
}

例外:

org.jboss.weld.exceptions.DeploymentException: WELD-001409 Ambiguous dependencies for type [Principal] with qualifiers [@Default] at injection point [[parameter 1] of [constructor] @Inject public my.package.MyType(Principal, SomeOtherType)]. Possible dependencies [[Producer Method [Principal] with qualifiers [@Any @Default] declared as [[method] @Produces @SessionScoped protected my.package.MyProducer.obtainPrincipal()], Built-in Bean [java.security.Principal] with qualifiers [@Default]]]
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:278)
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:244)
    at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:107)
    at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:127)
    at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.java:346)
    at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:331)
    at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:366)
    at org.jboss.as.weld.WeldContainer.start(WeldContainer.java:83)
    at org.jboss.as.weld.services.WeldService.start(WeldService.java:76)
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811)
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:722)

所以问题是 - 有没有办法替换CDI中的默认内置类型?

为了让您了解我为什么需要这个,我的项目正在从JAAS切换到Apache Shiro。有大量现有代码可以根据注入的主体执行某些操作。但是,Web环境中的Shiro只包装HttpServlet请求/响应并覆盖相应的安全相关方法。然而,这并没有传播到CDI,在这种情况下,CDI总是返回匿名主体。

更新 我也尝试了以下内容:

my.package;

import javax.security.Principal;

@Alternative
public class MyPrincipal implements Principal {


    ...

    @Override
    public String getName() {
        return getMyPrincipalName();
    }

}

然后在beans.xml中启用替代方法:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/beans_1_0.xsd">

    <alternatives>
        <class>my.package.MyPrincipal</class>
    </alternatives>

</beans>

在这种情况下,没有部署错误,但注入的主体仍然是默认的主体,而不是我启用的备选方案。

1 个答案:

答案 0 :(得分:3)

Weld的家伙帮助了我。我的部署结构类似于:

-- app.war
  |-- module0.jar (beans.xml)
  |-- module1.jar (beans.xml)
  |-- ...
  |-- other-lib.jar

但是在CDI 1.0中,只有每个bean存档才能使用替代品。所以,添加

<alternatives>
    <class>my.package.MyPrincipal</class>
</alternatives>
每个beans.xml中的

都可以使它全部工作。