Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inject dependencies in spring for objects created dynamically at run time?

public class PlatformEventFactory {

    public PlatformEvent createEvent(String eventType) {
        if (eventType.equals("deployment_activity")) {
            return new UdeployEvent();
        }


        return null;
    }
}

I have a factory class which creates PlatformEvent type objects based on the eventType.

UdeployEvent class has dependency on private RedisTemplate<String, Object> template on which I want to inject after the UdeployEvent object has been created.

@Component
public class UdeployEvent implements PlatformEvent {

    private RedisTemplate<String, Object> template;
    private UDeployMessage uDeployMessage;

    private static final Logger logger = LoggerFactory.getLogger(UdeployEvent.class);

    public UdeployEvent() {
        uDeployMessage = new UDeployMessage();
    }


    /*public void sendNotification() {

    }*/

    public RedisTemplate<String, Object> getTemplate() {
        return template;
    }

    @Autowired
    public void setTemplate(RedisTemplate<String, Object> template) {
        this.template = template;
        System.out.println("Injection done");
    }
}

When the new object is returned for UdeployEvent I get null pointer exception for template. I believe the reason for that is because it is not referring to the same bean which is created when spring boots up. How can I inject dependencides for newly created objects at run time.

like image 447
madcolonel10 Avatar asked Mar 09 '23 12:03

madcolonel10


1 Answers

You should not create components manually. Let Spring to do this. Use ApplicationContext to get instance of component. All fields will be automatically injected:

@Component
public class PlatformEventFactory {

    @Autowired
    private ApplicationContext context;

    public PlatformEvent createEvent(String eventType) {
        if (eventType.equals("deployment_activity")) {                
            return context.getBean(UdeployEvent.class);
        }

        return null;
    }
}

To make Spring create new instance of UdeployEvent component every time you request it, specify scope of component as SCOPE_PROTOTYPE:

@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class UdeployEvent implements PlatformEvent {

    private RedisTemplate<String, Object> template;

    public RedisTemplate<String, Object> getTemplate() {
        return template;
    }

    @Autowired
    public void setTemplate(RedisTemplate<String, Object> template) {
        this.template = template;
        System.out.println("Injection done");
    }

    ...
}

Now every time you call context.getBean(UdeployEvent.class) Spring will create new instance of component with fully initialized dependencies.

like image 175
Ken Bekov Avatar answered Mar 12 '23 05:03

Ken Bekov