glassfish
  1. glassfish
  2. GLASSFISH-18096

GlassFish ignores @Resource(authenticationType = AuthenticationType.CONTAINER) if no ejb-jar.xml is present in an EJB

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 3.1.1
    • Fix Version/s: 3.1.2_b17, 4.0
    • Component/s: deployment
    • Labels:
      None
    • Environment:

      Windows xp x86, JDK6u30, gf v3.1.1

      Description

      Summary: GlassFish ignores @Resource(authenticationType = AuthenticationType.CONTAINER) if no ejb-jar.xml is present in an EJB

      Setup: When creating a Connnector Connection Pool, GF has a Security Maps tab. Enter the following:

      Principal: *
      Backend Principal: uid/password

      Create an EJB with an injection point:

      @Stateless
      @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
      public class EchoServiceBean implements EchoService {

      @Resource(
      name = "view/EchoService",
      type = ViewManagerClientFactory.class,
      authenticationType = AuthenticationType.CONTAINER)
      ViewManagerClientFactory clientFactory;

      GlassFish will not pass the backend principal to the @Resource.

      To make this work, put the same information in the ejb-jar.xml:
      <session>
      <ejb-name>EchoServiceBean</ejb-name>
      <resource-ref>
      <res-ref-name>view/EchoService</res-ref-name>
      <res-type>com.argushealth.enterprise.viewmanager.ViewManagerClientFactory</res-type>
      <res-auth>Container</res-auth>
      </resource-ref>
      </session>

      The problem is in ConnectionManagerImpl. It uses pure XML to determine whether or not container managed authentication is required:

      if (ref == null) {

      if(getLogger().isLoggable(Level.FINE))

      { getLogger().log(Level.FINE, "poolmgr.no_resource_reference", jndiNameToUse); }

      return internalGetConnection(mcf, defaultPrin, cxRequestInfo,

      resourceShareable, jndiNameToUse, conn, true);

      }

      String auth = ref.getAuthorization();

      This should also examine the @Resource annotation, rather than just doing a null-check if a the resource reference descriptor is null.

      More info: http://www.java.net/forum/topic/glassfish/glassfish/gf-bug-getting-empty-credentials-jca-adapter

        Activity

        Hide
        Jagadish added a comment -

        The code in ConnectionManagerImpl retrieves the resource-reference which is a merged version of Annotation and Descriptor.
        So, in all cases (eg: annotation alone is specified), we would still get the resource-reference.

        connector-security-map is used to map the credentials from application server's security domain to EIS security domain.

        Please refer the sample test that uses security-map in an RAR and the settings in web.xml.
        https://svn.java.net/svn/glassfish~svn/trunk/v2/appserv-tests/devtests/connector/v3/securitymapweb

        • Refer "create-users" target in build.xml
        • Refer "create-security-maps" target in build.xml
        • Refer web.xml where the roles are defined for the web-component (it will be similar for ejb-component also)
          <security-constraint>
          <web-resource-collection>
          <web-resource-name>basic secuity test</web-resource-name>
          <url-pattern>/*</url-pattern>
          </web-resource-collection>
          <auth-constraint>
          <role-name>employee</role-name>
          <role-name>contractor</role-name>
          <role-name>management</role-name>
          </auth-constraint>
          </security-constraint>
          ..
          ..
          ..
          <security-role>
          <role-name>employee</role-name>
          </security-role>
          <security-role>
          <role-name>contractor</role-name>
          </security-role>
          <security-role>
          <role-name>management</role-name>
          </security-role>

        So, a role by name "employee" will be translated into "map3/map3" principal/password in EIS security domain via connector-security-map.

        Show
        Jagadish added a comment - The code in ConnectionManagerImpl retrieves the resource-reference which is a merged version of Annotation and Descriptor. So, in all cases (eg: annotation alone is specified), we would still get the resource-reference. connector-security-map is used to map the credentials from application server's security domain to EIS security domain. Please refer the sample test that uses security-map in an RAR and the settings in web.xml. https://svn.java.net/svn/glassfish~svn/trunk/v2/appserv-tests/devtests/connector/v3/securitymapweb Refer "create-users" target in build.xml Refer "create-security-maps" target in build.xml Refer web.xml where the roles are defined for the web-component (it will be similar for ejb-component also) <security-constraint> <web-resource-collection> <web-resource-name>basic secuity test</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>employee</role-name> <role-name>contractor</role-name> <role-name>management</role-name> </auth-constraint> </security-constraint> .. .. .. <security-role> <role-name>employee</role-name> </security-role> <security-role> <role-name>contractor</role-name> </security-role> <security-role> <role-name>management</role-name> </security-role> So, a role by name "employee" will be translated into "map3/map3" principal/password in EIS security domain via connector-security-map.
        Hide
        exabrial added a comment -

        Jagadish,

        I think you missed the entire point of me logging this bug. If you specify the settings in XML, it works, if you use annotations, it doesn't work.

        So your statements: "ConnectionManagerImpl retrieves the resource-reference which is a merged version of Annotation and Descriptor." is not true. I'm trying to log a bug and tell you the "merging" is not working.

        -Jonathan

        Show
        exabrial added a comment - Jagadish, I think you missed the entire point of me logging this bug. If you specify the settings in XML, it works, if you use annotations, it doesn't work. So your statements: "ConnectionManagerImpl retrieves the resource-reference which is a merged version of Annotation and Descriptor." is not true. I'm trying to log a bug and tell you the "merging" is not working. -Jonathan
        Hide
        Jagadish added a comment -

        Yes, I did try a pure annotation based resource injection and it worked fine.
        eg:
        @Resource(mappedName="jdbc/__default", shareable=false, authenticationType = AuthenticationType.APPLICATION)
        DataSource ds1;
        ds1.getConnection() //succeeded.

        Please attach a sample (eg: a sample based on jdbc or jms resource is also fine) if you see the issue.

        Show
        Jagadish added a comment - Yes, I did try a pure annotation based resource injection and it worked fine. eg: @Resource(mappedName="jdbc/__default", shareable=false, authenticationType = AuthenticationType.APPLICATION) DataSource ds1; ds1.getConnection() //succeeded. Please attach a sample (eg: a sample based on jdbc or jms resource is also fine) if you see the issue.
        Hide
        Jagadish added a comment -

        Actual annotation was :
        @Resource(mappedName="jdbc/__default", shareable=false, authenticationType = AuthenticationType.Container)
        DataSource ds1;

        Show
        Jagadish added a comment - Actual annotation was : @Resource(mappedName="jdbc/__default", shareable=false, authenticationType = AuthenticationType.Container) DataSource ds1;
        Hide
        exabrial added a comment -

        I just confirmed it works fine for me as well on JDBC resources... The problem seems to occur on custom resource adapters.

        I can create you a code example, but do you have a custom RAR laying around? If not, let me know and I'll create you an example.

        Otherwise, set a breakpoint on this method:
        public ManagedConnection createManagedConnection(Subject subject, ConnectionRequestInfo cxRequestInfo) throws ResourceException;

        My implementation is as follows:

        public ViewManagerConnection getConnection(Subject subject, ConnectionRequestInfo cxRequestInfo)
        throws ResourceException {
        String operatorId = null;
        String operatorPassword = null;

        if (overrideUserName != null)

        { operatorId = overrideUserName; operatorPassword = overridePassword; }

        else {
        for (PasswordCredential cred : subject.getPrivateCredentials(PasswordCredential.class)) {
        operatorId = cred.getUserName();
        operatorPassword = new String(cred.getPassword());

        if (operatorId != null && operatorPassword != null)

        { break; }

        }
        }
        ....

        Show
        exabrial added a comment - I just confirmed it works fine for me as well on JDBC resources... The problem seems to occur on custom resource adapters. I can create you a code example, but do you have a custom RAR laying around? If not, let me know and I'll create you an example. Otherwise, set a breakpoint on this method: public ManagedConnection createManagedConnection(Subject subject, ConnectionRequestInfo cxRequestInfo) throws ResourceException; My implementation is as follows: public ViewManagerConnection getConnection(Subject subject, ConnectionRequestInfo cxRequestInfo) throws ResourceException { String operatorId = null; String operatorPassword = null; if (overrideUserName != null) { operatorId = overrideUserName; operatorPassword = overridePassword; } else { for (PasswordCredential cred : subject.getPrivateCredentials(PasswordCredential.class)) { operatorId = cred.getUserName(); operatorPassword = new String(cred.getPassword()); if (operatorId != null && operatorPassword != null) { break; } } } ....
        Hide
        exabrial added a comment -

        Ok, I've spent 2 hours creating a test case for this bug and can easily reproduce it. Can we open the bug back up so I can add an attachment?

        Show
        exabrial added a comment - Ok, I've spent 2 hours creating a test case for this bug and can easily reproduce it. Can we open the bug back up so I can add an attachment?
        Hide
        Jagadish added a comment -

        re-opening the issue so as to attach the test-case.

        Show
        Jagadish added a comment - re-opening the issue so as to attach the test-case.
        Hide
        exabrial added a comment -

        JCA example

        Show
        exabrial added a comment - JCA example
        Hide
        exabrial added a comment - - edited

        To recreate the problem:

        1. run "mvn clean install" on all the projects in this order:
          1. glassfish-jca-problem
          2. glassfish-jca-problem-ejb
          3. glassfish-jca-problem-jca
          4. glassfish-jca-problem-ear
        2. deploy the resulting EAR to glassfish
        3. create a new pool using the rar in the ear
        4. create a security map for the rar. the security map should be * for the front end principal and put a test username/password in the backend principal
        5. create the following jndi reference to the pool: jca/MyJCA
        6. click this link, then click the doSomethingAwesome button: http://localhost:8080/MyJCAWebServiceService/MyJCAWebService?Tester

        Notice the username and password are empty

        To fix the problem, thus proving that an ejb-jar.xml must be present:

        1. rename this file: /glassfish-jca-problem-ejb/src/main/resources/META-INF/RENAME TO ejb-jar_XML to /glassfish-jca-problem-ejb/src/main/resources/META-INF/ejb-jar.xml
        2. run "mvn clean install" on all the projects in this order:
          1. glassfish-jca-problem
          2. glassfish-jca-problem-ejb
          3. glassfish-jca-problem-jca
          4. glassfish-jca-problem-ear
        3. redeploy the ear
        4. click this link, then click the doSomethingAwesome button: http://localhost:8080/MyJCAWebServiceService/MyJCAWebService?Tester

        Notice that a username and password are present

        Show
        exabrial added a comment - - edited To recreate the problem: run "mvn clean install" on all the projects in this order: glassfish-jca-problem glassfish-jca-problem-ejb glassfish-jca-problem-jca glassfish-jca-problem-ear deploy the resulting EAR to glassfish create a new pool using the rar in the ear create a security map for the rar. the security map should be * for the front end principal and put a test username/password in the backend principal create the following jndi reference to the pool: jca/MyJCA click this link, then click the doSomethingAwesome button: http://localhost:8080/MyJCAWebServiceService/MyJCAWebService?Tester Notice the username and password are empty To fix the problem, thus proving that an ejb-jar.xml must be present: rename this file: /glassfish-jca-problem-ejb/src/main/resources/META-INF/RENAME TO ejb-jar_XML to /glassfish-jca-problem-ejb/src/main/resources/META-INF/ejb-jar.xml run "mvn clean install" on all the projects in this order: glassfish-jca-problem glassfish-jca-problem-ejb glassfish-jca-problem-jca glassfish-jca-problem-ear redeploy the ear click this link, then click the doSomethingAwesome button: http://localhost:8080/MyJCAWebServiceService/MyJCAWebService?Tester Notice that a username and password are present
        Hide
        Jagadish added a comment -

        Thanks Jonathan. I am able to reproduce the issue.
        It looks like resource-env-ref is getting generated instead of resource-ref for @Resource annotation where type is a non standard class (eg: not one of javax.sql.DataSource/javax.jms.Queue/javax.jms.Topic etc.,). I shall investigate further and update the issue.

        Show
        Jagadish added a comment - Thanks Jonathan. I am able to reproduce the issue. It looks like resource-env-ref is getting generated instead of resource-ref for @Resource annotation where type is a non standard class (eg: not one of javax.sql.DataSource/javax.jms.Queue/javax.jms.Topic etc.,). I shall investigate further and update the issue.
        Hide
        exabrial added a comment -

        Thanks Jagadish, I really appreciate your time.

        Incidentally, and I'm not sure if this is related, but you cannot inject a java.lang.String as a @Resource. Not sure if that is part of the specification, but it could be related. String injection does work if the String is a resource-env-ref, but does not work if it's a resource-ref.

        Show
        exabrial added a comment - Thanks Jagadish, I really appreciate your time. Incidentally, and I'm not sure if this is related, but you cannot inject a java.lang.String as a @Resource. Not sure if that is part of the specification, but it could be related. String injection does work if the String is a resource-env-ref, but does not work if it's a resource-ref.
        Hide
        Hong Zhang added a comment -
        • What is the impact on the customer of the bug?
          Not a regression, but this is something specified in the JSR 250 (common annotation spec) but we missed in the initial implementation.
        • What is the cost/risk of fixing the bug?
          The fix is available (and checked into trunk). The risk is small to medium.
        • Is there an impact on documentation or message strings?
          No.
        • Which tests should QA (re)run to verify the fix did not destabilize GlassFish?
          Regular set of the tests.
        • Which is the targeted build of 3.1.2 for this fix?
          The next promoted build of 3.1.2.
        Show
        Hong Zhang added a comment - What is the impact on the customer of the bug? Not a regression, but this is something specified in the JSR 250 (common annotation spec) but we missed in the initial implementation. What is the cost/risk of fixing the bug? The fix is available (and checked into trunk). The risk is small to medium. Is there an impact on documentation or message strings? No. Which tests should QA (re)run to verify the fix did not destabilize GlassFish? Regular set of the tests. Which is the targeted build of 3.1.2 for this fix? The next promoted build of 3.1.2.
        Hide
        Hong Zhang added a comment -

        exabrial: Jagadish and I looked at the issue, it seems it's something we missed in the initial implementation (that a @Resource with a connection factory that's defined in resource adapter should be mapped to resource-ref and not resource-env-ref). Thanks for reporting this and providing the test case! I have checked in the fix into trunk (v4) and submitted a change request for approval to check the fix into 3.1.2 branch.
        For @Resource with String type, based on the spec (JSR250), it should be mapped to env-entry and the current implementation is consistent with that.

        Show
        Hong Zhang added a comment - exabrial: Jagadish and I looked at the issue, it seems it's something we missed in the initial implementation (that a @Resource with a connection factory that's defined in resource adapter should be mapped to resource-ref and not resource-env-ref). Thanks for reporting this and providing the test case! I have checked in the fix into trunk (v4) and submitted a change request for approval to check the fix into 3.1.2 branch. For @Resource with String type, based on the spec (JSR250), it should be mapped to env-entry and the current implementation is consistent with that.
        Hide
        Hong Zhang added a comment -

        fixed checked into both trunk and 3.1.2 branch.

        Show
        Hong Zhang added a comment - fixed checked into both trunk and 3.1.2 branch.

          People

          • Assignee:
            Hong Zhang
            Reporter:
            exabrial
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Time Tracking

              Estimated:
              Original Estimate - 3 days
              3d
              Remaining:
              Remaining Estimate - 3 days
              3d
              Logged:
              Time Spent - Not Specified
              Not Specified