4

I realize this should be really basic but I haven't found a second step example after Helloworld

So what I have is:

spring config xml called spring-beans.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <context:annotation-config />
    <context:component-scan base-package="org" />

</beans>

A spring context initialized class:

public static void main(String[] args) {
    // initialize Spring
    ApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring-beans.xml");

    App app = (App) context.getBean("app");
    app.run();
}

Relevant details of AppImpl class:

@Component("app")
public final class AppImpl implements App{    

    // focus of question: This autowiring works
    @Autowired
    private DAO1 dao1;


    public void run() {
        //focus of question: This works as daoclass is instantiated properly                   
        obj1s = dao1.myFind();            

        badJobs = runJobs(obj1s);
    }

    private List<Obj1> runJobs(final List<Obj1> obj1s) {        
        List<Obj1> jobsGoneBad = new ArrayList<Obj1>();
        for (Obj1 next : obj1s) {

            // focus of question: usage of new keyword, thus not spring container managed?
            Job job = new JobImpl(next);
            job.run();

        }
        return jobsGoneBad;
    }    
}

Relevant details of JobImpl:

public class JobImpl implements Job {

    private Obj1 obj1;

    // focus of question: can't autowire
    @Autowired
    private DAO2 dao2;

    @Override
    public void run() {
        //focus of question: opDAO == null - not initialized by @Autowired
        Obj2 obj2 = dao2.myFind();        
    }

}

Relevant details of DAO1:

@Repository("DAO1") //Focus of question: DAO1 is a repository stereotype
public class DAO1 {

    myfind() { ...}
}

Relevant details of DAO2:

@Repository("DAO2") //Focus of question: DAO2 is a repository stereotype
public class DAO2 {        

    myfind() { ...}
}

Right, so I initialize the App through a springcontext call and then succesfully instantiate a DAO1 instance through the use of @Autowired.

Then I create an unmanaged instance of Job and want to inject "singeltonish" dependencies in that class too by using @Autowired

Both Dao classes are spring stereotypes and scanner finds them fine.

So my question is basically, how should I instantiate the job instance so that I can use @Autowired concept inside it?

If I need a globally accessible applicationcontext, how do I best introduce that?

Rythmic
  • 759
  • 2
  • 10
  • 25

4 Answers4

5

You can use Spring Bean functionality like injection only in spring managed beans!

But you can use the @Configurable Annotation, but this requires that you use REAL AspectJ. If a class is annotated by @Configurable (and you use AspectJ) then you can use Springs Injection Annotations even if this class is created by a normal new.

@See

Community
  • 1
  • 1
Ralph
  • 118,862
  • 56
  • 287
  • 383
  • This info is relevant to solve the problem with the current design, but I think the problem is better solved with a re-design as suggested in another post. Still clearly worth an upvote! – Rythmic Oct 26 '12 at 11:55
2

Spring beans are singletons by default. However, what you need there are multiple instances, and on top of that, multiple instances created runtime.

One possibility is to use method injection for this. You'd create a container aware job factory that would request new instances from the container.

(I think it is a bit fishy that you'd need a DAO reference injected in those runtime instances... I would maybe try rethinking the logic. Why couldn't you just provide the DAO reference in a constructor argument, for example, or use it from somewhere else altogether. You could have a method in the dao that would accept a Jobs instance, or a runWith(DAO2 dao) stuff in the JobImpl that would be satisfied with a class injected elsewhere, or a JobProcessor service that would have the daos injected and would ask the relevant info from Jobs instance...)

eis
  • 51,991
  • 13
  • 150
  • 199
  • Thank you for being polite. :) would you mind elaborating on the "somewhere else altogether" thought. – Rythmic Oct 26 '12 at 11:01
2

@Autowired isn't working because your JobImpl object isn't managed by spring so it never has a chance to inject it. Spring managed beans are those where instances are created during component scan or in XML definition. JobImpl in your case is being instantiated as a normal Java object.

One solution would be to replace the auto-wiring with a manual lookup in the spring context.

private DAO2 dao2 = SpringApplicationContext.getApplicationContext ().getBean (DAO2.class);

@Autowired is working in @AppImpl because it's annotated as @Component. This flags it up for spring during its classpath scan where it will create an instance of this class and perform any autowiring/injections.

Ben Thurley
  • 6,943
  • 4
  • 31
  • 54
  • Thank you for your input. I knew why it wasn't working. I was more looking for input on the best alternative implementation to make it work. I don't think running to the application context each time I would need to solves it as good as the proposed redesign of another answer – Rythmic Oct 26 '12 at 12:16
0

Add @Component annotation to your JobImpl class. Add component scan for this class in xml and your autowiring will work for dao2(provide getter-setter methods).

Nandkumar Tekale
  • 16,024
  • 8
  • 58
  • 85
  • 1
    I don't think that's the problem - the problem is that he's creating the JobImpl class manually runtime, bypassing the spring container. – eis Oct 26 '12 at 10:28
  • I get that, but as you might have noticed the JobImpl receives an Obj1 constructor argument and is meant to process several thousands of them which voids the option of using @Component as it is not an object with singelton behavior. – Rythmic Oct 26 '12 at 11:27