4 Replies Latest reply on Mar 6, 2013 3:45 PM by rdcrng

    Override the built in Principal injection.

    rdcrng Newbie

      Hello CDI wizards!

       

      My project is switching from JAAS to Apache Shiro. We have a good amount CDI beans which rely on the current Principal being injected. In a Servlet environment Shiro simply wraps the HttpServletRequest and overrides the getRemoteUser() method. This means that injecting the current principal with CDI always injects the anonymous principal.

       

      I would like to have the Shiro principal injected the same way the Java EE principal is being injected so that we wouldn't have to modify existing code. At first, I tried a producer method:

       

      my.package;

      import javax.security.Principal;

      public class MyProducer {

          ...

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

       

      To not much surprise, this resulted in a deployment error:

       

      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 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)

       

      From the spec, at Chapter 15:

      In the Java EE environment, the container provides the following built-in beans, all with the qualifier @Default:

      • a Principal representing the current caller identity

       

      So I thought that declaring an alternative would solve my problem:

      my.package;

      import javax.security.Principal;

      @Alternative
      public class MyPrincipal implements Principal {


          ...

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

      }

       

      with 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>

       

      This, does not result in any deployment errors, but the injected principal is still the built in one.

       

      First off, is what I'm trying to achieve above (override the default built in bean) possible? If it is, please point me in the right direction. Otherwise, shouldn't the alternative example result in a deployment error as well?

       

      Thank you in advance for your help!