Following the directions in the Spring In Action book, I created a small application (only three Java files and two configuration files) so that I could experiment with method-level access control using ACEGI.

However, I continously saw a mysterious message in my log:

Public object - authentication not attempted

So naturally I started looking around the Internet for information about creating private objects. Sadly, there was none. Being stubborn, I downloaded the ACEGI source code to start poking around.

After an hour or so of adding logging messages and tracing the code, I saw the following message in my logging of the MethodDefinitionMap.lookupAttributes method:

...MethodDefinitionMap; this: {...public java.lang.String
com.affy.BeanA.getValue()=[ROLE_FIELD_OPS, ROLE_DIRECTORY,
ROLE_PRESIDENT]}

...MethodDefinitionMap; method: public abstract java.lang.String
com.affy.IBeanA.getValue()

At first I thought the problem lay in the abstract keyword. But then I realized that my Spring configuration file contained:

  <bean id='securityInterceptor' class='...MethodSecurityInterceptor'>
    ...
    <property name='objectDefinitionSource'>
      <value>
        com.affy.BeanA.setValue=ROLE_PRESIDENT
        com.affy.BeanA.getValue=ROLE_FIELD_OPS,ROLE_DIRECTORY,ROLE_PRESIDENT
      </value>
    </property>
 </bean>

The object definition specified the BeanA implementation instead of the Interface. Once I changed to use com.affy.IBean I saw the following message:

...AbstractSecurityInterceptor - Secure object: invocation: method
'setValue', arguments [FOOBAR]; target is of class [com.affy.BeanA];
ConfigAttributes: [ROLE_PRESIDENT]

Now the newly created object was private!

CONCLUSION Use Interfaces in the objectDefinitionSource specification.