长期以来,Java EE规范缺少批处理API。 今天,这对于企业应用程序来说是必不可少的。 这是最后固定与JSR-352批处理应用程序的Java平台现在的Java EE提供7 JSR-352得到了它的的灵感Spring Batch的对手。 两者涵盖相同的概念,尽管生成的API有所不同。
由于Spring团队也参与了JSR-352的合作,因此他们提供基于Spring Batch的实现只是时间问题。 Spring Batch的最新主版本(版本3)现在支持JSR-352 。
我是Spring Batch的用户很多年了,我一直很喜欢该技术具有一组有趣的内置读写器。 这些使您可以执行批处理所需的最常见操作。 您需要从数据库读取数据吗? 您可以使用JdbcCursorItemReader
,如何以固定格式写入数据? 使用FlatFileItemWriter
,依此类推。
不幸的是, JSR-352实现没有Spring Batch中可用的读写器数量。 我们必须记住, JSR-352是非常新的,没有时间跟上。 jBeret ( JSR-352的Wildfly实现)已经提供了一些自定义的读取器和写入器。
重点是什么?
我希望在最新版本中,也可以使用原始Spring Batch中的所有读者和作家。 目前还不是这样,因为需要大量工作,但是已经计划在将来的版本中提供它们。 这将使我们能够将本地Spring Batch应用程序迁移到JSR-352中 。 我们仍然存在实现供应商锁定的问题,但是在某些情况下这可能很有趣。
动机
我是JSR-352规范中的Java EE示例的主要测试贡献者之一。 我想弄清楚使用Spring Batch实现,我实现的测试是否具有相同的行为。 我们该怎么做?
码
我认为该练习不仅因为原始动机而有趣,而且对于了解Wildfly上的模块和类加载也很有用。 首先,我们需要决定如何部署所需的Spring Batch依赖项。 我们可以直接在应用程序中部署它们,也可以使用Wildfly模块。 模块的优点是可以直接捆绑到应用程序服务器中,并且可以被所有已部署的应用程序重用。
使用Maven添加Wildfly模块
通过一些工作,可以使用Wildfly Maven插件和CLI(命令行)自动添加模块。 让我们开始创建两个文件,它们代表创建和删除模块所需的CLI命令:
wildfly-add-spring-batch.cli
wildfly-add-spring-batch.cli
# Connect to Wildfly instance
connect
# Create Spring Batch Module
# If the module already exists, Wildfly will output a message saying that the module already exists and the script exits.
module add \
--name=org.springframework.batch \
--dependencies=javax.api,javaee.api \
--resources=${wildfly.module.classpath}
模块--name
很重要。 我们将需要它在我们的应用程序中引用它。 --resources
很--resources
,因为您需要为所有必需的模块依赖项指定完整的类路径,但是在接下来的几步中,我们将生成路径。
wildfly-remove-spring-batch.cli
wildfly-remove-spring-batch.cli
# Connect to Wildfly instance
connect
# Remove Oracle JDBC Driver Module
module remove --name=org.springframework.batch
注意wildfly.module.classpath
。 该属性将保存所需的Spring Batch依赖项的完整类路径。 我们可以使用Maven Dependency插件生成它:
pom-maven-dependency-plugin.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>${version.plugin.dependency}</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>build-classpath</goal>
</goals>
<configuration>
<outputProperty>wildfly.module.classpath</outputProperty>
<pathSeparator>:</pathSeparator>
<excludeGroupIds>javax</excludeGroupIds>
<excludeScope>test</excludeScope>
<includeScope>provided</includeScope>
</configuration>
</execution>
</executions>
</plugin>
这将选择所有依赖项(包括传递性),排除javax
(因为它们已经存在于Wildfly中 )并排除test
范围依赖项。 对于Spring Batch,我们需要以下依赖项:
pom-dependencies.xml
<!-- Needed for Wildfly module -->
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
<version>3.0.0.RELEASE</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.0.5.RELEASE</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.3.2</version>
<scope>provided</scope>
</dependency>
现在,我们需要替换文件中的属性。 让我们使用Maven资源插件 :
pom-maven-resources-plugin.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>${version.plugin.resources}</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/scripts</outputDirectory>
<resources>
<resource>
<directory>src/main/resources/scripts</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
这将过滤配置的文件,并将属性wildfly.module.classpath
替换为我们先前生成的值。 这是一个指向本地Maven存储库中依赖项的类路径。 现在,使用Wildfly Maven插件,我们可以执行以下脚本(您需要运行Wildfly ):
pom-maven-wildfly-plugin.xml
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<version>${version.plugin.wildfly}</version>
<configuration>
<skip>false</skip>
<executeCommands>
<batch>false</batch>
<scripts>
<!--suppress MavenModelInspection -->
<script>target/scripts/${cli.file}</script>
</scripts>
</executeCommands>
</configuration>
</plugin>
这些配置文件:
pom-profiles.xml
<profiles>
<profile>
<id>install-spring-batch</id>
<properties>
<cli.file>wildfly-add-spring-batch.cli</cli.file>
</properties>
</profile>
<profile>
<id>remove-spring-batch</id>
<properties>
<cli.file>wildfly-remove-spring-batch.cli</cli.file>
</properties>
</profile>
</profiles>
(有关pom.xml
的完整内容,请pom.xml
此处 )
我们可以通过执行以下命令添加模块:
mvn process-resources wildfly:execute-commands -P install-spring-batch
。
或通过执行以下命令删除模块:
mvn wildfly:execute-commands -P remove-spring-batch
。
该策略适用于要在Wildfly中创建的任何模块。 考虑添加JDBC驱动程序。 通常,您使用模块将其添加到服务器中,但是我发现的所有文档始终都是手动过程。 这对于CI构建非常有用,因此您可以拥有设置环境所需的一切。
使用Spring-Batch
好的,我的模块在那里,但是如何指示Wildfly代替jBeret使用它呢? 我们需要在应用程序的META-INF
文件夹中添加以下文件:
jboss-deployment-structure.xml
jboss-deployment-structure.xml
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<exclusions>
<module name="org.wildfly.jberet"/>
<module name="org.jberet.jberet-core"/>
</exclusions>
<dependencies>
<module name="org.springframework.batch" services="import" meta-inf="import"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
由于JSR-352使用服务加载程序加载实现,因此唯一可能的结果是加载org.springframework.batch
模块中指定的服务。 您的批处理代码现在将与Spring Batch实现一起运行。
测试中
github存储库代码中有Arquillian示例测试来演示行为。 检查下面的参考资料部分。
资源资源
您可以从我的github存储库中克隆完整的工作副本。 您可以在此处找到说明进行部署。
由于我将来可能会修改代码,因此您可以从1.0版中下载本文的原始源。 或者,克隆存储库,并使用以下命令从发行版1.0中检出标记: git checkout 1.0
。
未来
我仍然需要将此应用于Java EE示例 。 在我的待办事项清单上。
翻译自: https://www.javacodegeeks.com/2014/08/spring-batch-as-wildfly-module.html