Khushroo Mistry
Khushroo Mistry

Reputation: 161

Spring and Abstract class - injecting properties in abstract classes

I have an abstract base class with a property called "mailserver" which I wish to inject from the spring ioc container. However when I run the concreted implementations of the abstract class I get a null for the mailserver property.

What is the correct way of doing this? Have you tried doing someting like this and been successful? Please share.

Upvotes: 16

Views: 56490

Answers (3)

MadOverJava
MadOverJava

Reputation: 49

In my case, inside a Spring4 Application, i had to use a classic Abstract Factory Pattern(for which i took the idea from - http://java-design-patterns.com/patterns/abstract-factory/) to create instances each and every time there was a operation to be done.So my code was to be designed like:

public abstract class EO {
    @Autowired
    protected SmsNotificationService smsNotificationService;
    @Autowired
    protected SendEmailService sendEmailService;
    ...
    protected abstract void executeOperation(GenericMessage gMessage);
}

public final class OperationsExecutor {
    public enum OperationsType {
        ENROLL, CAMPAIGN
    }

    private OperationsExecutor() {
    }

    public static Object delegateOperation(OperationsType type, Object obj) 
    {
        switch(type) {
            case ENROLL:
                if (obj == null) {
                    return new EnrollOperation();
                }
                return EnrollOperation.validateRequestParams(obj);
            case CAMPAIGN:
                if (obj == null) {
                    return new CampaignOperation();
                }
                return CampaignOperation.validateRequestParams(obj);
            default:
                throw new IllegalArgumentException("OperationsType not supported.");
        }
    }
}

@Configurable(dependencyCheck = true)
public class CampaignOperation extends EO {
    @Override
    public void executeOperation(GenericMessage genericMessage) {
        LOGGER.info("This is CAMPAIGN Operation: " + genericMessage);
    }
}

Initially to inject the dependencies in the abstract class I tried all stereotype annotations like @Component, @Service etc but even though Spring context file had ComponentScanning for the entire package, but somehow while creating instances of Subclasses like CampaignOperation, the Super Abstract class EO was having null for its properties as spring was unable to recognize and inject its dependencies.After much trial and error I used this **@Configurable(dependencyCheck = true)** annotation and finally Spring was able to inject the dependencies and I was able to use the properties in the subclass without cluttering them with too many properties.

<context:annotation-config />
<context:component-scan base-package="com.xyz" />

I also tried these other references to find a solution:

  1. http://www.captaindebug.com/2011/06/implementing-springs-factorybean.html#.WqF5pJPwaAN
  2. http://forum.spring.io/forum/spring-projects/container/46815-problem-with-autowired-in-abstract-class
  3. https://github.com/cavallefano/Abstract-Factory-Pattern-Spring-Annotation
  4. http://www.jcombat.com/spring/factory-implementation-using-servicelocatorfactorybean-in-spring
  5. https://www.madbit.org/blog/programming/1074/1074/#sthash.XEJXdIR5.dpbs
  6. Using abstract factory with Spring framework
  7. Spring Autowiring not working for Abstract classes
  8. Inject spring dependency in abstract super class
  9. Spring autowire dependency defined in an abstract class
    1. Spring can you autowire inside an abstract class?

Please try using **@Configurable(dependencyCheck = true)** and update this post, I might try helping you if you face any problems.

Upvotes: 0

Ryan Stewart
Ryan Stewart

Reputation: 128829

Properties in superclasses, abstract or not, are injected exactly the same as any other properties in Spring. You can use setter, constructor, or field injection based on XML, annotations, or Java config. You'll find extensive use of inheritance all across Spring: the DefaultMessageListenerContainer, for example. Show how you're trying to wire the property, and someone can give you an explanation of why it's not working.

Upvotes: 2

Ken Chan
Ken Chan

Reputation: 90447

Mark the abstract base class definition as abstract by using the abstract attribute , and in the concrete class definition , make the parent attribute be the name of the abstract class 's bean name

Something like this:

<bean id="abstractBaseClass" abstract="true" class="pacakge1.AbstractBaseClass">
  <property name="mailserver" value="DefaultMailServer"/>
</bean>

<bean id="concreteClass1" class="pacakge1.ConcreteClass1" parent="abstractBaseClass">     
  <!--Override the value of the abstract based class if necessary-->
  <property name="mailserver" value="AnotherMailServer"/>
</bean>

Upvotes: 12

Related Questions