更上一層樓
VMware 提供培訓和認證,以加速你的進展。
了解更多在本文中,我將向您展示如何在 SpringSource 應用平台中執行 Spring Batch job。我運行了一個早期版本,作為 JavaOne 的一個小演示,然後又在倫敦 Spring User Group 中運行,並認為分享它可能是一件好事。 範例程式碼在這裡。
套件組態位於META-INF/spring/module-context.xml(這是 Platform 套件的慣例) - Spring DM 會從META-INF/spring中提取所有 XML 檔案。 這個只是使用 Spring 來配置和啟動 HSQL Server 的一個實例。
有一個整合測試可用於檢查組態。
Eclipse 專案還包含 HSQL Swing 客戶端的啟動組態,因此您可以在 GUI 中看到資料庫內容。 啟動它並使用以下屬性連接到伺服器實例META-INF/batch-hsql.properties在同一個專案中 (url=jdbc:hsqldb:hsql://localhost:9005/samples)。
套件組態位於META-INF/spring/module-context.xml一如既往。 它是simple-job-launcher-context.xml的精簡版本,來自 Spring Batch 範例。 它只需要定義要匯出的 beans,即
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="databaseType" value="hsql" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
唯一的另一個配置是JobRepository的交易建議(Spring Batch 1.1 中不需要)。 dataSource 參考來自data-source套件以上公開的 OSGi 服務。 要了解如何導入該參考以及如何將本地服務公開到 OSGi Service Registry,我們可以查看META-INF/spring/osgi-context.xml:
<reference id="dataSource" interface="javax.sql.DataSource" />
<service ref="jobLauncher"
interface="org.springframework.batch.core.launch.JobLauncher" />
<service ref="jobRepository"
interface="org.springframework.batch.core.repository.JobRepository" />
<service ref="transactionManager"
interface="org.springframework.transaction.PlatformTransactionManager" />
這是 Spring DM 的非常直接的使用。 重要的一點是,模組上下文與 OSGi 特定的上下文分開。 這使我們可以為模組上下文編寫整合測試,而無需部署到 Platform。 因此我們有
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class JobLauncherIntegrationTests {
@Autowired
private JobLauncher jobLauncher;
@Test
public void testLaunchJob() throws Exception {
assertNotNull(jobLauncher);
}
}
該測試載入上下文,添加本地資料來源定義以取代 OSGi 定義(請參閱JobLauncherIntegrationTests-context.xml),然後斷言 job launcher 可用。 您可以直接從 Eclipse 以正常方式執行測試。
...
Export-Package: com.springsource.consulting.batch.support
...
如果您查看此套件,您會發現一個方便的類,其他套件可以使用它來啟動 job (SimpleJobLauncherBean)。 TheSimpleJobLauncherBeanis anApplicationListener這意味著任何 SpringApplicationContext包含其中一個的都將嘗試在啟動時(載入上下文時)啟動 job。 它通過監聽ContextRefreshedEvent然後嘗試啟動 job
try {
jobLauncher.run(job, converter.getJobParameters(parameters));
} catch (JobExecutionAlreadyRunningException e) {
logger.error("This job is already running", e);
} catch (JobInstanceAlreadyCompleteException e) {
logger.info("This job is already complete. "
+ "Maybe you need to change the input parameters?", e);
} catch (JobRestartException e) {
logger.error("Unspecified restart exception", e);
}
啟動 job 的計畫是簡單地為每個 job 建立一個套件,並讓它定義其中一個SimpleJobLauncherBean實例。
將套件放入運行的伺服器實例中。 它啟動速度非常快,並且由於 job 的範圍很小,您將立即在批次元資料中看到效果。 在 HSQL Swing GUI 中,您可以執行一些 SQL,例如
SELECT * FROM BATCH_STEP_EXECUTION
並查看結果,如下所示
STEP_EXECUTION_ID | VERSION | STEP_NAME | ... | STATUS | ... |
---|---|---|---|---|---|
0 | 4 | helloWorldStep | ... | COMPLETED | ... |
這表示 job 已執行(並成功完成)。 步驟的組態位於META-INF/spring/module-context.xml:
<bean
class="com.springsource.consulting.batch.support.SimpleJobLauncherBean">
<constructor-arg ref="jobLauncher" />
<constructor-arg ref="helloWorld" />
<property name="parameters" value="launch.timestamp=${launch.timestamp}"/>
</bean>
<bean id="helloWorld" parent="simpleJob">
<property name="steps">
<bean parent="simpleStep" id="helloWorldStep">
<property name="commitInterval" value="100" />
<property name="itemReader">
...
</property>
<property name="itemWriter">
...
</property>
</bean>
</property>
</bean>
從上面您可以看到我們有一個常規的 Spring Batch job 組態(稱為 "helloWorld"),其中包含一個步驟。 步驟 ID ("helloWorldStep") 在上面的資料庫查詢中已經看到,表示該步驟已經執行過(一次)。 該步驟所做的只是從平面檔案讀取資料,將行轉換為網域物件,並將其寫入 stdout。 您可以通過檢查 Platform 主目錄中的追蹤日誌來查看結果,例如,如果您tail -f serviceability/trace/trace.log | grep -i hello您應該看到
[2008-05-30 15:57:04.140] platform-dm-11
com.springsource.consulting.batch.hello.MessageWriter.unknown
I Message: [Hello World]
[2008-05-30 15:57:04.140] platform-dm-11
com.springsource.consulting.batch.hello.MessageWriter.unknown
I Message: [Hello Small World]
如果您願意,您可以再次運行 job,只需編輯套件中的一個檔案(例如 MANIFEST 或其中一個 Spring 配置檔案)並保存即可。 這些工具會獲取更改並重新部署套件。 由於此 job 的設定方式,它會使用一組新的參數(使用時間戳記)啟動每次執行,因此它應該始終成功運行。
為了表示 job 的結束,SimpleJobLauncherBean只是獲取封閉的 OSGiBundle實例,然後停止它。 這是一個非常簡單的模型,但具有以下優點:API 已明確定義並受到 OSGi 平台普遍支持。 原則上,只要容器 (SpringSource 應用平台) 可以捕獲這些套件事件,它就可以非常靈活地擴展。 這些是我們可能會在 Platform 2.0 版的 Batch 個性化中看到的功能。 如果您對行為應該是什麼以及操作員需要哪些功能有任何想法,請通過評論本文來幫助我們。
我們可以通過登錄 Equinox 控制台來驗證 job 套件的狀態。 如果您轉到命令行並輸入telnet localhost 2401您應該會看到平台上的命令提示符
osgi>
輸入 "ss" 並點擊返回,您將看到已安裝套件的列表
osgi> ss
Framework is launched.
id State Bundle
...
86 RESOLVED org.springframework.batch.infrastructure_1.0.0
87 RESOLVED org.springframework.batch.core_1.0.0
88 RESOLVED com.springsource.org.apache.commons.lang_2.4.0
97 ACTIVE job.launcher_1.0.0
99 RESOLVED hello.world_1.0.0
osgi>
因此,id=97 的套件是 job launcher,它是活動的。 id=99 的套件是 hello world job(在您的情況下,id 可能不同),它是已解析的,但由於 job 完成執行時已停止,因此它不是活動的。
您可以從 OSGi 命令行再次重新啟動 job
osgi> start 99
osgi> ss
Framework is launched.
id State Bundle
...
86 RESOLVED org.springframework.batch.infrastructure_1.0.0
87 RESOLVED org.springframework.batch.core_1.0.0
88 RESOLVED com.springsource.org.apache.commons.lang_2.4.0
97 ACTIVE job.launcher_1.0.0
99 RESOLVED hello.world_1.0.0
osgi>
job 套件恢復到已解析狀態,但它再次執行了 job,您可以像以前一樣從 HSQL GUI 或從追蹤日誌進行驗證。
STEP_EXECUTION_ID | VERSION | STEP_NAME | ... | STATUS | ... |
---|---|---|---|---|---|
0 | 4 | helloWorldStep | ... | COMPLETED | ... |
1 | 4 | helloWorldStep | ... | COMPLETED | ... |
2 | 4 | helloWorldStep | ... | COMPLETED | ... |
如果你剛才試過這樣做,你可能會發現,在第二次及後續的啟動中,資料庫沒有任何變化。這是預期的,因為你重新啟動了一個成功完成的 Job 實例,所以它不會再次處理資料。實際上,JobLauncher拋出了一個例外,並且被SimpleJobLauncherBean捕獲並記錄下來(所以它會顯示在追蹤日誌中)。
安裝 SpringSource Eclipse 工具後,你需要建立一個伺服器實例。轉到檔案->新增->其他... 並找到伺服器->伺服器。選擇 SpringSource 和下面的伺服器類型,然後使用瀏覽對話方塊找到平台安裝目錄。
$ find ~/.m2/repository -name \*.jar -exec cp {} bundles/usr \;
無需重新啟動 Eclipse 或任何東西。「套件相依性」類別路徑容器應包含你剛剛下載的執行時期相依性。當問題視圖中的所有 Eclipse 錯誤(憤怒的紅色邊距標記)都消失時,我們就可以開始了。
我很樂意聽到有更好方法的人的回饋。其他人已經發展了其他方法,但對我來說似乎都不太方便。實際上,編寫一個命令列 Maven 目標會非常容易,但我還沒有看到過。
原則上,你根本不需要用於執行時期相依性的 Maven 本地儲存庫。你可以打開平台執行階段(在伺服器視圖中右鍵單擊並打開),然後直接瀏覽並下載相依性到bundles/usr。目前唯一的弱點(工具團隊正在努力改進這一點)是它不提供任何傳遞相依性的視圖 - 你必須明確知道需要哪些套件。對於此部落格的範例來說,這很容易,因為 MANIFESTs 都已經完全指定了相依性。當你不確定它們是什麼並且必須從頭開始建立 MANIFEST 時,這會更困難。為此,我現在仍然使用 Q4E。
Application Platform 1.0 版本的大部分重點都在網路層,雖然這顯然是必不可少的(而且非常難以實現),但還有其他目標需要努力。 2.0 版本將具有特定的批次相關功能(批次個性),因此我們現在所做的任何事情都將有助於充實該版本的特性要求。因此,如果你有機會嘗試一下並有一些建設性的意見,特別是關於操作方面的,它們將在我們開始構建批次個性時派上用場。