简体   繁体   中英

Bean found in ApplicationContext, but not found when attempting to Autowire

I have a Spring JobLauncher implementation I am trying to autowire into a @Component class, let's say it's called SimpleComponent . This job launcher, called SomeJobLauncher , is being loaded into the Spring context via bean definition.

If I autowire in the Spring application context into the SimpleComponent , and attempt to get the bean via getBean("someLauncher") , I get my bean, and there are no problems.

However, despite confirming that the bean is 100% loaded into the ApplicationContext, when I try to autowire someLauncher into SimpleComponent , I get this error:

No matching bean of type [com.somepackage.SomeJobLauncher] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Here are several of the relevant classes. Due to the enormous size of this application I can't show every single xml config file/Java class, but if there is something specific you'd like to see, I'm open to requests.

So would anyone have any clues to how this could be possible?

public class SomeJobLauncher extends BatchScheduleJobLauncher {

    private static final long serialVersionUID = 89457928374294789723L;
    /**
     * Spring inject the appropriate Server name from the Batch properties file.
     */
    @Value("${dataload.schedule.server}")
    private String jobSchedulerServer;


    /**
     * No-argument constructor.
     */
    public SomeJobLauncher() {
    }



    @Override
    protected String supplyScheduleServer() {
        return this.jobobSchedulerServer;
    }

}

Parent class:

public abstract class BatchScheduleJobLauncher extends SimpleJobLauncher implements Serializable {

    private static final long serialVersionUID = -1138294811959957159L;

    private String batchJobIdentifier = "not set";
    /**
     * Set by Spring property setting from the specific JobConfig.xml file inside the
     * WEB project.
     */
    private Job job;
    /**
     * Set by Spring property setting from the specific JobConfig.xml file inside the
     * WEB project.
     */
    private JobLauncher jobLauncher;
    /**
     * Set by Spring injection from within the descendent's implementation of the supplyScheduleServer
     * method.
     */
    private String jobSchedulerServer;


    /**
     * No argument constructor
     * Default Constructor
     */
    public BatchScheduleJobLauncher() {
    }


    /**
     * Spring invoked method.
     * 
     * @return org.springframework.batch.core.Job - Interface
     */
    public Job getJob() {
        return this.job;
    }

    /**
     * Spring invoked method.
     * 
     * @return org.springframework.batch.core.launch.JobLauncher - Interface
     */
    public JobLauncher getJobLauncher() {
        return this.jobLauncher;
    }

    /**
     * Method invoked from the corresponding Job Config XML file in the WEB
     * project or from the "Upon Demand" manual invocation process.
     * 
     * @return JobExecution - see internal "Status" for Job Completion
     *         indication.</br> Status set by this method is either
     *         BatchStatus.ABANDONED, BatchStatus.COMPLETED or
     *         BatchStatus.FAILED.
     */
    public JobExecution launch() {
        JobExecution returnValue;
        String timeParameter = "time";
        long systemTime = System.currentTimeMillis();
        JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
        JobParameters jobParameters;
        String ipAddressDefinedServer;
        ExitStatus exitStatus;

        // Build System Time Job parameter.
        jobParametersBuilder.addLong(timeParameter, systemTime);
        jobParameters = jobParametersBuilder.toJobParameters();

        this.batchJobIdentifier = supplyJobIdentifier();
        this.jobSchedulerServer = supplyScheduleServer();

        try {
            if (Util.isNullOrEmpty(this.jobSchedulerServer)) {
                LoggerUtil.error("Batch Job Scheduler Server NOT set on BatchScheduleJobLauncher ancestor class for the [" +
                                 this.batchJobIdentifier + "] Batch Load Job so 'run' could not be executed.");
                returnValue = new JobExecution(new JobInstance(new Long(0),
                                                               jobParameters, 
                                                               supplyJobIdentifier()));
                exitStatus = new ExitStatus(ExitStatus.FAILED.getExitCode());
                returnValue.setExitStatus(exitStatus);
                returnValue.setEndTime(new Date());
                returnValue.setStatus(BatchStatus.ABANDONED);
            } else {
                ipAddressDefinedServer = InetAddress.getLocalHost().getHostName();
                if (this.jobSchedulerServer.equalsIgnoreCase(ipAddressDefinedServer)) { 
                    // job scheduled server found.
                    LoggerUtil.info("Executing 'run' from inside the launch method of the BatchScheduleJobLauncher object.");
                    returnValue = this.jobLauncher.run(this.job, jobParameters);
                } else {
                    LoggerUtil.warn("Batch Job Scheduler Server ["  + this.jobSchedulerServer + 
                                    "] does NOT match the server name [" + ipAddressDefinedServer +
                                    "] found at IP Address [" + InetAddress.getLocalHost() +
                                    "] so 'run' could not be executed.");
                    returnValue = new JobExecution(new JobInstance(new Long(0),
                                                                   jobParameters, 
                                                                   supplyJobIdentifier()));
                    exitStatus = new ExitStatus(ExitStatus.FAILED.getExitCode());
                    returnValue.setExitStatus(exitStatus);
                    returnValue.setEndTime(new Date());
                    returnValue.setStatus(BatchStatus.ABANDONED);
                }
            }
        } catch (Exception e) {
            LoggerUtil.error("ERROR while running the BatchScheduleJobLauncher for the [" +
                             this.batchJobIdentifier + "] Batch Load Job. Error is [" + e.getMessage()+ "].");
            returnValue = new JobExecution(new JobInstance(new Long(0),
                                                           jobParameters, 
                                                           supplyJobIdentifier()));
            returnValue.addFailureException(e);
            returnValue.setStatus(BatchStatus.FAILED);
        }

        return returnValue;
    }

    /**
     * Called by Spring based on the property attributes in the corresponding
     * Job Config XML file.</br> Sets {@link #job}.
     * 
     * @param org.springframework.batch.core.Job - Interface
     */
    public void setJob(Job inJob) {
        this.job = inJob;
    }

    /**
     * Called by Spring based on the property attributes in the corresponding
     * Job Config XML file.</br> Sets {@link #jobLauncher}.
     * 
     * @param org.springframework.batch.core.Job - Interface
     */
    public void setJobLauncher(JobLauncher inJobLauncher) {
        this.jobLauncher = inJobLauncher;
    }

    /**
     * Must be implemented by the descendant Job Launcher job to define the type
     * of Batch job being run.</br> Sets {@link #batchJobIdentifier}.
     * 
     * @return String - the batch job type.
     */
    abstract protected String supplyJobIdentifier();

    /**
     * Must be implemented by the descendant Job Launcher job to define the
     * specific schedule Server name.</br> The appropriate value will be Spring
     * injected (see someJobLauncher.java).</br> Sets {@link #jobSchedulerServer}.
     * 
     * @return String - the scheduler server name.
     */
    abstract protected String supplyScheduleServer();
}

Bean definitions for the launcher:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

   <tx:annotation-driven proxy-target-class="true" />

  <bean id="transactionManager"
    class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />

  <bean id="jobRepository"
    class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
    <property name="transactionManager" ref="transactionManager" />
  </bean>

  <bean id="jobLauncher" 
    class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
    <property name="jobRepository" ref="jobRepository" />
  </bean>
</beans>

Bean definitions for the job:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:batch="http://www.springframework.org/schema/batch"
  xmlns:task="http://www.springframework.org/schema/task"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/task
    http://www.springframework.org/schema/task/spring-task-3.0.xsd
    http://www.springframework.org/schema/batch
    http://www.springframework.org/schema/batch/spring-batch-2.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <tx:annotation-driven proxy-target-class="true" />

  <!-- Multiple threading not needed so set pool size to one. -->
  <task:scheduler id="scheduler" pool-size="1" />   

  <bean id="someLoadJob" class="com.somepackage.SomeLoadJob" />

  <!-- Once Excel File is found on the Load Job landing zone the Batch Load will be run -->
  <!-- This Job Instance must always run as a new Job. -->
  <batch:job id="processLoadJob" restartable="false">
    <batch:step id="processLoadJobStep">
      <batch:tasklet ref="LoadJob" />
    </batch:step>
  </batch:job>

  <bean id="someLauncher" class="com.somepackage.SomeJobLauncher">
    <property name="jobLauncher" ref="jobLauncher"></property>
    <property name="jobRepository" ref="jobRepository"></property>
    <property name="job" ref="processLoadJob"></property>
  </bean>

  <task:scheduled-tasks scheduler="scheduler">
  <task:scheduled ref="someLauncher" method="launch" cron="${batch.scheduler.time}"/>
  </task:scheduled-tasks>

</beans>

Autowiring class. You'll have to take my word this this class is getting component scanned.

@Component
public class SimpleComponent {

    private Map<String, JobCategoryStatus> jobStatuses = new HashMap<String, JobCategoryStatus>();;
    private Map<String, List<JobCategoryStatus>> categoryStatuses = new HashMap<String, List<JobCategoryStatus>>();

//  public SimpleComponent() { };

    @Autowired
    private ApplicationContext ctx;

    //This autowire doesn't work
    @Autowired
    private SomeJobLauncher someLauncher;

    //This method works
    public SomeJobLauncher getSomeLauncher() {
         Object someLauncher = ctx.getBean("someLauncher");
         return someLauncher;
    }



}

I may be missing something but I don't see you turning on component scanning (). Because you aren't scanning components and SimpleComponent isn't defined in your context, I wouldn't expect Spring to Autowire it. Once you turn on component scanning for the package you want, I'd expect this to work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM