1

I'm using Spring MVC 3.2.4 and Apache Commons Pooling 2.3 for managing connections to a SOAP service. One of the things I am using is the "idle object eviction" thread feature in the GenericObjectPool class:

http://commons.apache.org/proper/commons-pool/api-2.3/org/apache/commons/pool2/impl/GenericObjectPool.html

With this feature I specify the name of the class to use to test for eviction of our connection objects:

http://commons.apache.org/proper/commons-pool/api-2.3/org/apache/commons/pool2/impl/BaseObjectPoolConfig.html#setEvictionPolicyClassName(java.lang.String)

Upon inspection of the Commons Pooling implementation of the GenericObjectPool class, the eviction class is instantiated using reflection and executed. All attempts to inject Spring beans into this class have failed including using common techniques such as load-time weaving using @EnableLoadTimeWeaving and @Configurable on the generated class.

Is it possible to inject Spring beans into a class that is generated internally by reflection and is not managed by the Spring container?

EDIT:

Here is the method that instantiates the evictor class:

 ...

 public final void setEvictionPolicyClassName(
        String evictionPolicyClassName) {
    try {
        Class<?> clazz = Class.forName(evictionPolicyClassName);
        Object policy = clazz.newInstance();
        if (policy instanceof EvictionPolicy<?>) {
            @SuppressWarnings("unchecked") // safe, because we just checked the class
            EvictionPolicy<T> evicPolicy = (EvictionPolicy<T>) policy;
            this.evictionPolicy = evicPolicy;
        }
    } catch (ClassNotFoundException e) {

    ...

Here is the run method executed within the thread on a set interval:

  ...

  @Override
    public void run() {
        ClassLoader savedClassLoader =
                Thread.currentThread().getContextClassLoader();
        try {
            // Set the class loader for the factory
            Thread.currentThread().setContextClassLoader(
                    factoryClassLoader);

            // Evict from the pool
            try {
                evict();
            } catch(Exception e) {

     ...

Here is a sample of the implementation of the EvictionPolicy class:

  class SampleEvictionPolicy implements EvictionPolicy<SabreConnection> {

// This is what I would like to add:
// @Autowired
// private desiredBeans desiredBeans

public SampleEvictionPolicy() { }

@Override
boolean evict(EvictionConfig evictionConfig, PooledObject<SabreConnection> tPooledObject, int i) {
   // Do some stuff
}
skel625
  • 876
  • 3
  • 7
  • 17

1 Answers1

1

If I understand you correctly, you have a problem to "bridge" non-spring classes with spring beans. If I understand correctly, the instantiation and execution of that checks are out of your control (see final method there). So my suggestion is simple (although not so nice):

  1. Make the spring bean you need available via some static method/field (~ singleton pattern) and set it during spring initialization.
  2. Make normal (non-spring) class that will get this bean via this static method and calls the needed checks.
  3. Register this class with apache commons.
sodik
  • 4,675
  • 2
  • 29
  • 47
  • This was actually my first thought when considering options, but I need to access classes shared throughout the app and managed by Spring. I would have either had to create duplicate classes or convert everything to not be spring managed beans, neither a very good option. So what I've done for now is passed a reference to the spring managed beans into the eviction class which works well. I will suggest a change to Apache Commons to allow the eviction class to be passed as a reference which would allow it to be Spring managed. Not sure of why it is not that way now but I'll try to find out. – skel625 Feb 05 '15 at 18:12