Spring批处理集成—如何让远程执行JVM上的StepLocator能够看到作业外部的远程步骤?
我已经为远程分区配置了我的作业,我正在通过kafka发送消息,从VM正在接收请求并尝试启动该步骤,但它找不到该步骤 我提供的beanFactory(applicationContext)似乎不包含远程执行步骤 我已经多次浏览了这个示例,但是我不知道如何为从属作业识别和设置正确的beanFactory 在应用程序初始化期间,从作业库加载ClasspathXmlApplicationContextsFactoryBean,其中包含所有spring批处理作业和远程从属步骤的XML。这个bean包含每个XML文件的单独资源,包括从属文件(如预期的),并分配给applicationContextSpring批处理集成—如何让远程执行JVM上的StepLocator能够看到作业外部的远程步骤?,spring,spring-integration,spring-batch,Spring,Spring Integration,Spring Batch,我已经为远程分区配置了我的作业,我正在通过kafka发送消息,从VM正在接收请求并尝试启动该步骤,但它找不到该步骤 我提供的beanFactory(applicationContext)似乎不包含远程执行步骤 我已经多次浏览了这个示例,但是我不知道如何为从属作业识别和设置正确的beanFactory 在应用程序初始化期间,从作业库加载ClasspathXmlApplicationContextsFactoryBean,其中包含所有spring批处理作业和远程从属步骤的XML。这个bean包含每个
@Bean
public ClasspathXmlApplicationContextsFactoryBean classpathXmlApplicationContextsFactoryBean () throws IOException
{
String resourcePath = configPropertiesService
.fetchPropertyValue(PropertyValueConstants.MXARCHIVE_SKELETON_LOCATION,
PropertyValueConstants.MXARCHIVE_SKELETON_LOCATION_DEFAULT)
.getValue() + "*.xml";
logger.trace("classpathXmlApplicationContextsFactoryBean() :: {} ", resourcePath);
Resource[] resources = applicationContext.getResources(resourcePath);
ClasspathXmlApplicationContextsFactoryBean bean = new ClasspathXmlApplicationContextsFactoryBean ();
bean.setApplicationContext(applicationContext);
bean.setResources(resources);
return bean;
}
@Bean
public BeanFactoryStepLocator stepLocator() throws Exception
{
BeanFactoryStepLocator stepLocator = new BeanFactoryStepLocator ();
/* applicationContext is autowired in the postconstruct - what we do here doesn't matter
stepLocator.setBeanFactory(applicationContext); // TODO: Find the right factory
*/
return stepLocator;
};
// EDIT: added method to code listing so the calling method is visible
@Bean
public StepExecutionRequestHandler stepExecutionRequestHandler() throws Exception {
StepExecutionRequestHandler result = new StepExecutionRequestHandler();
;
result.setJobExplorer(jobExplorer);
BeanFactoryStepLocator stepLocator = stepLocator ();
result.setStepLocator(stepLocator);
return result;
}
BeanFactoryStepLocator使用applicationContext初始化
@Bean
public ClasspathXmlApplicationContextsFactoryBean classpathXmlApplicationContextsFactoryBean () throws IOException
{
String resourcePath = configPropertiesService
.fetchPropertyValue(PropertyValueConstants.MXARCHIVE_SKELETON_LOCATION,
PropertyValueConstants.MXARCHIVE_SKELETON_LOCATION_DEFAULT)
.getValue() + "*.xml";
logger.trace("classpathXmlApplicationContextsFactoryBean() :: {} ", resourcePath);
Resource[] resources = applicationContext.getResources(resourcePath);
ClasspathXmlApplicationContextsFactoryBean bean = new ClasspathXmlApplicationContextsFactoryBean ();
bean.setApplicationContext(applicationContext);
bean.setResources(resources);
return bean;
}
@Bean
public BeanFactoryStepLocator stepLocator() throws Exception
{
BeanFactoryStepLocator stepLocator = new BeanFactoryStepLocator ();
/* applicationContext is autowired in the postconstruct - what we do here doesn't matter
stepLocator.setBeanFactory(applicationContext); // TODO: Find the right factory
*/
return stepLocator;
};
// EDIT: added method to code listing so the calling method is visible
@Bean
public StepExecutionRequestHandler stepExecutionRequestHandler() throws Exception {
StepExecutionRequestHandler result = new StepExecutionRequestHandler();
;
result.setJobExplorer(jobExplorer);
BeanFactoryStepLocator stepLocator = stepLocator ();
result.setStepLocator(stepLocator);
return result;
}
在执行时,框架尝试调用该步骤,但失败,因为该步骤不在应用程序上下文(beanFactory)中
步骤XML(已清理)是:
创建时stepLocator中beanFactory的调试器视图
stepLocator()工厂方法结尾处getStep()结果的调试器视图:
编辑2:
看起来原始的“applicationContext”是作为beanfactory自动连接的,所以真正的问题是将额外的bean加载到applicationContext中
@Bean
public ClasspathXmlApplicationContextsFactoryBean classpathXmlApplicationContextsFactoryBean () throws IOException
{
String resourcePath = configPropertiesService
.fetchPropertyValue(PropertyValueConstants.MXARCHIVE_SKELETON_LOCATION,
PropertyValueConstants.MXARCHIVE_SKELETON_LOCATION_DEFAULT)
.getValue() + "*.xml";
logger.trace("classpathXmlApplicationContextsFactoryBean() :: {} ", resourcePath);
Resource[] resources = applicationContext.getResources(resourcePath);
ClasspathXmlApplicationContextsFactoryBean bean = new ClasspathXmlApplicationContextsFactoryBean ();
bean.setApplicationContext(applicationContext);
bean.setResources(resources);
return bean;
}
@Bean
public BeanFactoryStepLocator stepLocator() throws Exception
{
BeanFactoryStepLocator stepLocator = new BeanFactoryStepLocator ();
/* applicationContext is autowired in the postconstruct - what we do here doesn't matter
stepLocator.setBeanFactory(applicationContext); // TODO: Find the right factory
*/
return stepLocator;
};
// EDIT: added method to code listing so the calling method is visible
@Bean
public StepExecutionRequestHandler stepExecutionRequestHandler() throws Exception {
StepExecutionRequestHandler result = new StepExecutionRequestHandler();
;
result.setJobExplorer(jobExplorer);
BeanFactoryStepLocator stepLocator = stepLocator ();
result.setStepLocator(stepLocator);
return result;
}
我还尝试了在和链接问题上建议的解决方案。您可以尝试向BeanFactory声明所需的依赖关系,并让Spring提供正确的实例,而不是手动执行查找/注入。因此,不是:
@Bean
public BeanFactoryStepLocator stepLocator() throws Exception {
BeanFactoryStepLocator stepLocator = new BeanFactoryStepLocator();
ApplicationContextFactory[] factories = stepFactoryBean().getObject();
if (factories != null) {
stepLocator.setBeanFactory(factories[0].createApplicationContext().getBeanFactory());
}
return stepLocator;
};
使用类似于:
@Bean
public StepLocator stepLocator(BeanFactory beanFactory) {
BeanFactoryStepLocator beanFactoryStepLocator = new BeanFactoryStepLocator();
beanFactoryStepLocator.setBeanFactory(beanFactory);
return beanFactoryStepLocator;
}
希望这有帮助。您可以尝试向BeanFactory声明所需的依赖项,并让Spring提供正确的实例,而不是手动执行查找/注入。因此,不是:
@Bean
public BeanFactoryStepLocator stepLocator() throws Exception {
BeanFactoryStepLocator stepLocator = new BeanFactoryStepLocator();
ApplicationContextFactory[] factories = stepFactoryBean().getObject();
if (factories != null) {
stepLocator.setBeanFactory(factories[0].createApplicationContext().getBeanFactory());
}
return stepLocator;
};
使用类似于:
@Bean
public StepLocator stepLocator(BeanFactory beanFactory) {
BeanFactoryStepLocator beanFactoryStepLocator = new BeanFactoryStepLocator();
beanFactoryStepLocator.setBeanFactory(beanFactory);
return beanFactoryStepLocator;
}
希望这有帮助。我已经发现beanFactory属性与根应用程序上下文自动关联,覆盖了我们在代码中设置的任何内容。目前,
stepLocator()
方法仅返回与applicationContext
自动连接的newbeanfactorysteplocator()
的结果。如前所述,我可以在applicationContext的alreadyCreated
属性中看到StepBean,但stepLocator无法找到该步骤。我已更新了代码剪报,以表明设置beanFactory是一件麻烦事。我们是否可以安排一次会议,以便我们可以一起讨论?问题并不是我们期望的那样,我的时间表很紧。谢谢。我建议您在项目()的gitter频道上提问,团队很乐意提供帮助。我已经发现beanFactory属性与根应用程序上下文自动关联,覆盖了我们在代码中设置的任何内容。目前,stepLocator()
方法仅返回与applicationContext
自动连接的newbeanfactorysteplocator()
的结果。如前所述,我可以在applicationContext的alreadyCreated
属性中看到StepBean,但stepLocator无法找到该步骤。我已更新了代码剪报,以表明设置beanFactory是一件麻烦事。我们是否可以安排一次会议,以便我们可以一起讨论?问题并不是我们期望的那样,我的时间表很紧。谢谢。我建议您在项目的gitter频道()上提问,团队将乐于提供帮助。